added EntrancePoint entity, extended entity NodePath support
This commit is contained in:
parent
b76ae7cb96
commit
5a0a536ef5
|
|
@ -4,11 +4,12 @@ import Entity
|
|||
import DistributedEntity
|
||||
import NodePath
|
||||
|
||||
# this is an abstract class, do not instantiate.
|
||||
class NodePathAttribs:
|
||||
"""Derive from this class to give an entity the behavior of a
|
||||
NodePath, without necessarily deriving from NodePath. Derived class
|
||||
must implement getNodePath()."""
|
||||
# base class for entities that support NodePath attributes
|
||||
# *** Don't derive directly from this class; derive from the appropriate
|
||||
# specialized class from the classes defined below.
|
||||
class NodePathEntityBase:
|
||||
# we don't call this __init__ because it doesn't have to be called
|
||||
# upon object init
|
||||
def initNodePathAttribs(self, doReparent=1):
|
||||
"""Call this after the entity has been initialized"""
|
||||
self.callSetters('pos','x','y','z',
|
||||
|
|
@ -17,9 +18,64 @@ class NodePathAttribs:
|
|||
if doReparent:
|
||||
self.callSetters('parentEntId')
|
||||
|
||||
self.getNodePath().setName('%s-%s' %
|
||||
(self.__class__.__name__, self.entId))
|
||||
|
||||
if __debug__:
|
||||
# for the editor
|
||||
self.getNodePath().setTag('entity', '1')
|
||||
|
||||
def setParentEntId(self, parentEntId):
|
||||
self.parentEntId = parentEntId
|
||||
self.level.requestReparent(self, self.parentEntId)
|
||||
|
||||
def destroy(self):
|
||||
if __debug__:
|
||||
# for the editor
|
||||
self.getNodePath().clearTag('entity')
|
||||
|
||||
# Entities that already derive from NodePath and Entity should derive
|
||||
# from this class
|
||||
class NodePathAttribs(NodePathEntityBase):
|
||||
def initNodePathAttribs(self, doReparent=1):
|
||||
NodePathEntityBase.initNodePathAttribs(self, doReparent)
|
||||
|
||||
def destroy(self):
|
||||
NodePathEntityBase.destroy(self)
|
||||
|
||||
def getNodePath(self):
|
||||
return self
|
||||
|
||||
# Entities that already derive from Entity, and do not derive from NodePath,
|
||||
# but want to be a NodePath, should derive from this.
|
||||
class NodePathAndAttribs(NodePathEntityBase, NodePath.NodePath):
|
||||
def __init__(self):
|
||||
node = hidden.attachNewNode('EntityNodePath')
|
||||
NodePath.NodePath.__init__(self, node)
|
||||
|
||||
def initNodePathAttribs(self, doReparent=1):
|
||||
NodePathEntityBase.initNodePathAttribs(self, doReparent)
|
||||
|
||||
def destroy(self):
|
||||
NodePathEntityBase.destroy(self)
|
||||
self.removeNode()
|
||||
|
||||
def getNodePath(self):
|
||||
return self
|
||||
|
||||
# Entities that already derive from Entity, and do not derive from NodePath,
|
||||
# but HAVE a NodePath that they want to represent them, should derive from
|
||||
# this. They must define getNodePath(), which should return their 'proxy'
|
||||
# NodePath instance.
|
||||
class NodePathAttribsProxy(NodePathEntityBase):
|
||||
def initNodePathAttribs(self, doReparent=1):
|
||||
"""Call this after the entity has been initialized"""
|
||||
NodePathEntityBase.initNodePathAttribs(self, doReparent)
|
||||
assert self.getNodePath() != self
|
||||
|
||||
def destroy(self):
|
||||
NodePathEntityBase.destroy(self)
|
||||
|
||||
def setPos(self, *args): self.getNodePath().setPos(*args)
|
||||
def setX(self, *args): self.getNodePath().setX(*args)
|
||||
def setY(self, *args): self.getNodePath().setY(*args)
|
||||
|
|
@ -37,85 +93,39 @@ class NodePathAttribs:
|
|||
|
||||
def reparentTo(self, *args): self.getNodePath().reparentTo(*args)
|
||||
|
||||
def setParentEntId(self, parentEntId):
|
||||
self.parentEntId = parentEntId
|
||||
self.level.requestReparent(self, self.parentEntId)
|
||||
|
||||
# this is an abstract class, do not instantiate.
|
||||
class NodePathSelfAttribs:
|
||||
"""Derive from this class to give an entity that is already a Nodepath
|
||||
the behavior of a NodePathEntity, with ability to reparent and be
|
||||
picked from the Direct/FactoryEditor interface"""
|
||||
def initNodePathSelfAttribs(self):
|
||||
if __debug__:
|
||||
self.setTag('entity', '1')
|
||||
self.callSetters('parentEntId')
|
||||
|
||||
def setParentEntId(self, parentEntId):
|
||||
self.parentEntId = parentEntId
|
||||
self.level.requestReparent(self, self.parentEntId)
|
||||
|
||||
|
||||
class privNodePathImpl(NodePath.NodePath):
|
||||
def __init__(self, name):
|
||||
node = hidden.attachNewNode(name)
|
||||
# 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 that 'are' NodePaths.
|
||||
class NodePathEntity(Entity.Entity, NodePath.NodePath, NodePathAttribs):
|
||||
def __init__(self, level, entId):
|
||||
node = hidden.attachNewNode('NodePathEntity')
|
||||
NodePath.NodePath.__init__(self, node)
|
||||
if __debug__:
|
||||
self.setTag('entity', '1')
|
||||
|
||||
def initNodePathAttribs(self):
|
||||
"""Call this after the entity has been initialized, and all
|
||||
of its attributes have been set"""
|
||||
self.callSetters('pos','x','y','z',
|
||||
'hpr','h','p','r',
|
||||
'scale','sx','sy','sz',
|
||||
'parentEntId')
|
||||
|
||||
def setParentEntId(self, parentEntId):
|
||||
self.parentEntId = parentEntId
|
||||
self.level.requestReparent(self.getNodePath(), self.parentEntId)
|
||||
Entity.Entity.__init__(self, level, entId)
|
||||
NodePathAttribs.initNodePathAttribs(self)
|
||||
|
||||
def destroy(self):
|
||||
if __debug__:
|
||||
self.clearTag('entity')
|
||||
NodePathAttribs.destroy(self)
|
||||
Entity.Entity.destroy(self)
|
||||
self.removeNode()
|
||||
|
||||
def getNodePath(self):
|
||||
return self
|
||||
|
||||
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):
|
||||
privNodePathImpl.__init__(self, '')
|
||||
Entity.Entity.__init__(self, level, entId)
|
||||
self.setName(str(self))
|
||||
privNodePathImpl.initNodePathAttribs(self)
|
||||
|
||||
def destroy(self):
|
||||
Entity.Entity.destroy(self)
|
||||
privNodePathImpl.destroy(self)
|
||||
|
||||
def getNodePath(self):
|
||||
return self
|
||||
|
||||
# This is a distributed version of NodePathEntity. It should not
|
||||
# be instantiated directly; distributed entities that are also NodePaths
|
||||
# may derive from this instead of DistributedEntity.
|
||||
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."""
|
||||
NodePath.NodePath, NodePathAttribs):
|
||||
def __init__(self, cr):
|
||||
DistributedEntity.DistributedEntity.__init__(self, cr)
|
||||
privNodePathImpl.__init__(self, 'DistributedNodePathEntity')
|
||||
node = hidden.attachNewNode('DistributedNodePathEntity')
|
||||
NodePath.NodePath.__init__(self, node)
|
||||
|
||||
def announceGenerate(self):
|
||||
DistributedEntity.DistributedEntity.announceGenerate(self)
|
||||
privNodePathImpl.initNodePathAttribs(self)
|
||||
NodePathAttribs.initNodePathAttribs(self)
|
||||
|
||||
def destroy(self):
|
||||
DistributedEntity.DistributedEntity.destroy(self)
|
||||
privNodePathImpl.destroy(self)
|
||||
def disable(self):
|
||||
NodePathAttribs.destroy(self)
|
||||
DistributedEntity.DistributedEntity.disable(self)
|
||||
|
||||
def getNodePath(self):
|
||||
return self
|
||||
def delete(self):
|
||||
self.removeNode()
|
||||
DistributedEntity.DistributedEntity.delete(self)
|
||||
|
|
|
|||
|
|
@ -81,6 +81,16 @@ class DistributedLevel(DistributedObject.DistributedObject,
|
|||
# zone the entire time we're in here
|
||||
self.levelZone = zoneId
|
||||
|
||||
def setPlayerIds(self, avIdList):
|
||||
self.avIdList = avIdList
|
||||
assert toonbase.localToon.doId in self.avIdList
|
||||
|
||||
def setEntranceId(self, entranceId):
|
||||
self.entranceId = entranceId
|
||||
|
||||
def getEntranceId(self):
|
||||
return self.entranceId
|
||||
|
||||
# "required" fields (these ought to be required fields, but
|
||||
# the AI level obj doesn't know the data values until it has been
|
||||
# generated.)
|
||||
|
|
@ -168,6 +178,19 @@ class DistributedLevel(DistributedObject.DistributedObject,
|
|||
# load stuff
|
||||
self.initVisibility()
|
||||
|
||||
self.placeLocalToon()
|
||||
|
||||
def placeLocalToon(self):
|
||||
# the entrancePoint entities register themselves with us
|
||||
if self.entranceId not in self.entranceId2entity:
|
||||
self.notify.warning('unknown entranceId %s' % self.entranceId)
|
||||
toonbase.localToon.setPos(0,0,0)
|
||||
else:
|
||||
epEnt = self.entranceId2entity[self.entranceId]
|
||||
epEnt.placeToon(toonbase.localToon,
|
||||
self.avIdList.index(toonbase.localToon.doId),
|
||||
len(self.avIdList))
|
||||
|
||||
def createEntityCreator(self):
|
||||
"""Create the object that will be used to create Entities.
|
||||
Inheritors, override if desired."""
|
||||
|
|
|
|||
|
|
@ -13,11 +13,20 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
|
|||
"""DistributedLevelAI"""
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLevelAI')
|
||||
|
||||
def __init__(self, air, zoneId):
|
||||
def __init__(self, air, zoneId, entranceId, avIds):
|
||||
DistributedObjectAI.DistributedObjectAI.__init__(self, air)
|
||||
Level.Level.__init__(self)
|
||||
# this is one of the required fields
|
||||
# these are required fields
|
||||
self.zoneId = zoneId
|
||||
self.entranceId = entranceId
|
||||
|
||||
assert len(avIds) > 0 and len(avIds) <= 4
|
||||
assert 0 not in avIds
|
||||
assert None not in avIds
|
||||
self.avIdList = avIds
|
||||
self.numPlayers = len(self.avIdList)
|
||||
self.notify.debug("expecting avatars: %s" % str(self.avIdList))
|
||||
|
||||
if __debug__:
|
||||
self.modified = 0
|
||||
|
||||
|
|
@ -37,6 +46,12 @@ class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI,
|
|||
same zone with the level"""
|
||||
return self.zoneId
|
||||
|
||||
def getPlayerIds(self):
|
||||
return self.avIdList
|
||||
|
||||
def getEntranceId(self):
|
||||
return self.entranceId
|
||||
|
||||
def delete(self):
|
||||
self.notify.debug('delete')
|
||||
if __debug__:
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ class Entity(DirectObject):
|
|||
del self.level
|
||||
del self.entId
|
||||
|
||||
def getZoneEntId(self):
|
||||
"""returns entId of zone that contains this entity"""
|
||||
return self.level.getEntityZoneEntId(self.entId)
|
||||
|
||||
def privGetSetter(self, attrib):
|
||||
setFuncName = 'set%s%s' % (string.upper(attrib[0]), attrib[1:])
|
||||
if hasattr(self, setFuncName):
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import EntityCreatorBase
|
|||
import BasicEntities
|
||||
import DirectNotifyGlobal
|
||||
import EditMgr
|
||||
import EntrancePoint
|
||||
import LevelMgr
|
||||
import ZoneEntity
|
||||
import ModelEntity
|
||||
|
|
@ -14,7 +15,8 @@ import PathEntity
|
|||
# ctor functions must take (level, entId)
|
||||
# and they must return the entity that was created, or 'nothing'
|
||||
def nothing(*args):
|
||||
"""For entities that don't need to be created by the client"""
|
||||
"""For entities that don't need to be created by the client or don't
|
||||
exist on the client at all"""
|
||||
return 'nothing'
|
||||
|
||||
class EntityCreator(EntityCreatorBase.EntityCreatorBase):
|
||||
|
|
@ -29,6 +31,7 @@ class EntityCreator(EntityCreatorBase.EntityCreatorBase):
|
|||
self.privRegisterTypes({
|
||||
'cutScene': CutScene.CutScene,
|
||||
'editMgr': EditMgr.EditMgr,
|
||||
'entrancePoint': EntrancePoint.EntrancePoint,
|
||||
'levelMgr': LevelMgr.LevelMgr,
|
||||
'logicGate': nothing,
|
||||
'model' : ModelEntity.ModelEntity,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class EntityCreatorAI(EntityCreatorBase.EntityCreatorBase):
|
|||
self.privRegisterTypes({
|
||||
'cutScene': nothing,
|
||||
'editMgr': Functor(cLE, EditMgrAI.EditMgrAI),
|
||||
'entrancePoint': nothing,
|
||||
'levelMgr': Functor(cLE, LevelMgrAI.LevelMgrAI),
|
||||
'logicGate': Functor(cLE, LogicGateAI.LogicGateAI),
|
||||
'model' : nothing,
|
||||
|
|
|
|||
|
|
@ -53,6 +53,12 @@ class Zone(Nodepath):
|
|||
('visibility', [], 'visZoneList'),
|
||||
)
|
||||
|
||||
class EntrancePoint(Nodepath):
|
||||
type = 'entrancePoint'
|
||||
attribs = (
|
||||
('entranceId', -1, 'int'),
|
||||
)
|
||||
|
||||
class LogicGate(Entity):
|
||||
type = 'logicGate'
|
||||
output = 'bool'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
from ToontownGlobals import *
|
||||
import DirectNotifyGlobal
|
||||
import BasicEntities
|
||||
import NodePath
|
||||
|
||||
class EntrancePoint(BasicEntities.NodePathEntity):
|
||||
def __init__(self, level, entId):
|
||||
BasicEntities.NodePathEntity.__init__(self, level, entId)
|
||||
self.initEntrancePoint()
|
||||
|
||||
def destroy(self):
|
||||
self.destroyEntrancePoint()
|
||||
BasicEntities.NodePathEntity.destroy(self)
|
||||
|
||||
def placeToon(self, toon, toonIndex, numToons):
|
||||
toon.setPosHpr(self, 0,0,0, 0,0,0)
|
||||
|
||||
def initEntrancePoint(self):
|
||||
if self.entranceId >= 0:
|
||||
self.level.entranceId2entity[self.entranceId] = self
|
||||
|
||||
def destroyEntrancePoint(self):
|
||||
if self.entranceId >= 0:
|
||||
if self.level.entranceId2entity.has_key(self.entranceId):
|
||||
del self.level.entranceId2entity[self.entranceId]
|
||||
|
||||
if __debug__:
|
||||
def attribChanged(self, *args):
|
||||
BasicEntities.NodePathEntity.attribChanged(self, *args)
|
||||
self.destroyEntrancePoint()
|
||||
self.initEntrancePoint()
|
||||
|
|
@ -53,6 +53,9 @@ class Level:
|
|||
self.entType2ids = self.levelSpec.getEntType2ids(
|
||||
self.levelSpec.getAllEntIds())
|
||||
|
||||
# entranceId to entrance entity
|
||||
self.entranceId2entity = {}
|
||||
|
||||
# this list contains the entIds of entities that we have actually
|
||||
# created, in order of creation
|
||||
self.createdEntIds = []
|
||||
|
|
@ -198,6 +201,19 @@ class Level:
|
|||
def getEntityType(self, entId):
|
||||
return self.levelSpec.getEntityType(entId)
|
||||
|
||||
def getEntityZoneEntId(self, entId):
|
||||
"""return entId of zone that contains the entity"""
|
||||
return self.levelSpec.getEntityZoneEntId(entId)
|
||||
|
||||
def getEntityZoneNum(self, entId):
|
||||
"""return the model zoneNum of zone that contains the entity"""
|
||||
return self.levelSpec.getEntityZoneNum(entId)
|
||||
|
||||
def getEntityZoneId(self, entId):
|
||||
"""return network zoneId of zone that contains the entity"""
|
||||
zoneEntId = self.getEntityZoneEntId(entId)
|
||||
return self.zoneEntId2zoneId[entId]
|
||||
|
||||
def getZoneId(self, dummy=None, zoneNum=None, entId=None):
|
||||
"""look up network zoneId by zoneNum or entId"""
|
||||
assert (zoneNum is not None) or (entId is not None)
|
||||
|
|
|
|||
|
|
@ -103,6 +103,26 @@ class LevelSpec:
|
|||
def getEntityType(self, entId):
|
||||
return self.getEntitySpec(entId)['type']
|
||||
|
||||
def getEntityZoneEntId(self, entId):
|
||||
""" return the entId of the zone that entity is in; if entity
|
||||
is a zone, returns its entId """
|
||||
spec = self.getEntitySpec(entId)
|
||||
type = spec['type']
|
||||
# if it's a zone, this is our entity
|
||||
if type == 'zone':
|
||||
return entId
|
||||
# if we have no parentEntId, assume we're in the UberZone
|
||||
if not spec.has_key('parentEntId'):
|
||||
return LevelConstants.UberZoneEntId
|
||||
# keep looking up the heirarchy for a zone entity
|
||||
return self.getEntityZoneId(spec['parentEntId'])
|
||||
|
||||
def getEntityZoneNum(self, entId):
|
||||
""" return the model zoneNum of zone that contains the entity """
|
||||
zoneEntId = self.getEntityZoneEntId(entId)
|
||||
spec = self.getEntitySpec(zoneEntId)
|
||||
return spec['modelZoneNum']
|
||||
|
||||
def getEntType2ids(self, entIds):
|
||||
"""given list of entIds, return dict of entType 2 entIds"""
|
||||
entType2ids = {}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,11 @@ class ZoneEntity(ZoneEntityBase.ZoneEntityBase, BasicEntities.NodePathAttribs):
|
|||
ZoneEntityBase.ZoneEntityBase.__init__(self, level, entId)
|
||||
|
||||
self.nodePath = self.level.getZoneNode(self.modelZoneNum)
|
||||
self.initNodePathAttribs(doReparent=0)
|
||||
BasicEntities.NodePathAttribs.initNodePathAttribs(self, doReparent=0)
|
||||
|
||||
def destroy(self):
|
||||
BasicEntities.NodePathAttribs.destroy(self)
|
||||
ZoneEntityBase.ZoneEntityBase.destroy(self)
|
||||
|
||||
def getNodePath(self):
|
||||
return self.nodePath
|
||||
|
|
|
|||
Loading…
Reference in New Issue