コード例 #1
0
    def initializeDropShadow(self, hasGeomNode=True):
        """
        Load up and arrange the drop shadow
        """
        assert self.notify.debugStateCall(self)
        # First, protect this function from being called twice by
        # removing the old ones first.
        self.deleteDropShadow()

        # This will be used by the shadow system to identify things
        # that might want to have projected shadows drawn.
        if hasGeomNode:
            self.getGeomNode().setTag('cam', 'caster')

        # make the object float above the shadow slightly
        # not necessarily a good idea for all avatars
        # self.getGeomNode().setZ(0.025)

        # load and prep the drop shadow
        dropShadow = loader.loadModel(self.shadowFileName)
        dropShadow.setScale(
            0.4)  # Slightly smaller to compensate for billboard

        dropShadow.flattenMedium()
        dropShadow.setBillboardAxis(2)  # slide the shadow towards the camera
        dropShadow.setColor(
            0.0, 0.0, 0.0, globalDropShadowGrayLevel, 1
        )  # override of 1 to prevent avatar.setColor() from affecting shadows.
        self.shadowPlacer = ShadowPlacer(base.shadowTrav, dropShadow,
                                         OTPGlobals.WallBitmask,
                                         OTPGlobals.FloorBitmask)
        self.dropShadow = dropShadow
        if not globalDropShadowFlag:
            self.dropShadow.hide()
        if self.getShadowJoint():
            dropShadow.reparentTo(self.getShadowJoint())
        else:
            self.dropShadow.hide()

        # Set the state of the shadow placers (in case someone set the
        # value before now):
        self.setActiveShadow(self.wantsActive)

        self.__globalDropShadowFlagChanged()
        self.__globalDropShadowGrayLevelChanged()
コード例 #2
0
 def initializeDropShadow(self, hasGeomNode = True):
     self.deleteDropShadow()
     if hasGeomNode:
         self.getGeomNode().setTag('cam', 'caster')
     dropShadow = loader.loadModel(self.shadowFileName)
     dropShadow.setScale(0.4)
     dropShadow.flattenMedium()
     dropShadow.setBillboardAxis(2)
     dropShadow.setColor(0.0, 0.0, 0.0, globalDropShadowGrayLevel, 1)
     self.shadowPlacer = ShadowPlacer(base.shadowTrav, dropShadow, OTPGlobals.WallBitmask, OTPGlobals.FloorBitmask)
     self.dropShadow = dropShadow
     if not globalDropShadowFlag:
         self.dropShadow.hide()
     if self.getShadowJoint():
         dropShadow.reparentTo(self.getShadowJoint())
     else:
         self.dropShadow.hide()
     self.setActiveShadow(self.wantsActive)
     self.__globalDropShadowFlagChanged()
     self.__globalDropShadowGrayLevelChanged()
コード例 #3
0
class ShadowCaster:
    __module__ = __name__
    notify = DirectNotifyGlobal.directNotify.newCategory('ShadowCaster')

    def __init__(self, squareShadow=False):
        if squareShadow:
            self.shadowFileName = 'phase_3/models/props/square_drop_shadow'
        else:
            self.shadowFileName = 'phase_3/models/props/drop_shadow'
        self.dropShadow = None
        self.shadowPlacer = None
        self.activeShadow = 0
        self.wantsActive = 1
        self.storedActiveState = 0
        if (hasattr(base, 'wantDynamicShadows') and base).wantDynamicShadows:
            messenger.accept('globalDropShadowFlagChanged', self,
                             self.__globalDropShadowFlagChanged)
            messenger.accept('globalDropShadowGrayLevelChanged', self,
                             self.__globalDropShadowGrayLevelChanged)
        return

    def delete(self):
        if (hasattr(base, 'wantDynamicShadows') and base).wantDynamicShadows:
            messenger.ignore('globalDropShadowFlagChanged', self)
            messenger.ignore('globalDropShadowGrayLevelChanged', self)
        self.deleteDropShadow()
        self.shadowJoint = None
        return

    def initializeDropShadow(self, hasGeomNode=True):
        self.deleteDropShadow()
        if hasGeomNode:
            self.getGeomNode().setTag('cam', 'caster')
        dropShadow = loader.loadModel(self.shadowFileName)
        dropShadow.setScale(0.4)
        dropShadow.flattenMedium()
        dropShadow.setBillboardAxis(2)
        dropShadow.setColor(0.0, 0.0, 0.0, globalDropShadowGrayLevel, 1)
        self.shadowPlacer = ShadowPlacer(base.shadowTrav, dropShadow,
                                         OTPGlobals.WallBitmask,
                                         OTPGlobals.FloorBitmask)
        self.dropShadow = dropShadow
        if not globalDropShadowFlag:
            self.dropShadow.hide()
        if self.getShadowJoint():
            dropShadow.reparentTo(self.getShadowJoint())
        else:
            self.dropShadow.hide()
        self.setActiveShadow(self.wantsActive)
        self.__globalDropShadowFlagChanged()
        self.__globalDropShadowGrayLevelChanged()

    def update(self):
        pass

    def deleteDropShadow(self):
        if self.shadowPlacer:
            self.shadowPlacer.delete()
            self.shadowPlacer = None
        if self.dropShadow:
            self.dropShadow.removeNode()
            self.dropShadow = None
        return

    def setActiveShadow(self, isActive=1):
        isActive = isActive and self.wantsActive
        if not globalDropShadowFlag:
            self.storedActiveState = isActive
        if self.shadowPlacer != None:
            isActive = isActive and globalDropShadowFlag
            if self.activeShadow != isActive:
                self.activeShadow = isActive
                if isActive:
                    self.shadowPlacer.on()
                else:
                    self.shadowPlacer.off()
        return

    def setShadowHeight(self, shadowHeight):
        if self.dropShadow:
            self.dropShadow.setZ(-shadowHeight)

    def getShadowJoint(self):
        if hasattr(self, 'shadowJoint'):
            return self.shadowJoint
        shadowJoint = self.find('**/attachShadow')
        if shadowJoint.isEmpty():
            self.shadowJoint = NodePath(self)
        else:
            self.shadowJoint = shadowJoint
        return self.shadowJoint

    def hideShadow(self):
        if self.dropShadow != None:
            self.dropShadow.hide()
        return

    def showShadow(self):
        if self.dropShadow != None:
            if not globalDropShadowFlag:
                self.dropShadow.hide()
            else:
                self.dropShadow.show()
        return

    def __globalDropShadowFlagChanged(self):
        if self.dropShadow != None:
            if globalDropShadowFlag == 0:
                if self.activeShadow == 1:
                    self.storedActiveState = 1
                    self.setActiveShadow(0)
            else:
                if self.activeShadow == 0:
                    self.setActiveShadow(1)
            self.showShadow()
        return

    def __globalDropShadowGrayLevelChanged(self):
        if self.dropShadow != None:
            self.dropShadow.setColor(0.0, 0.0, 0.0, globalDropShadowGrayLevel,
                                     1)
        return
コード例 #4
0
class ShadowCaster:
    notify = DirectNotifyGlobal.directNotify.newCategory("ShadowCaster")

    # notify.setDebug(1)

    def __init__(self, squareShadow=False):
        assert self.notify.debugStateCall(self)
        # some shadow initialization stuff
        if squareShadow:
            self.shadowFileName = "phase_3/models/props/square_drop_shadow"
        else:
            self.shadowFileName = "phase_3/models/props/drop_shadow"

        self.dropShadow = None
        self.shadowPlacer = None
        self.activeShadow = 0
        self.wantsActive = 1
        self.storedActiveState = 0

        # Only create these hooks if we're running a game that cares
        # about them.
        if hasattr(base, "wantDynamicShadows") and base.wantDynamicShadows:
            messenger.accept('globalDropShadowFlagChanged', self,
                             self.__globalDropShadowFlagChanged)
            messenger.accept('globalDropShadowGrayLevelChanged', self,
                             self.__globalDropShadowGrayLevelChanged)

    def delete(self):
        assert self.notify.debugStateCall(self)

        # Only remove these hooks if we're running a game that cares
        # about them.
        if hasattr(base, "wantDynamicShadows") and base.wantDynamicShadows:
            messenger.ignore('globalDropShadowFlagChanged', self)
            messenger.ignore('globalDropShadowGrayLevelChanged', self)
        self.deleteDropShadow()
        self.shadowJoint = None

    def initializeDropShadow(self, hasGeomNode=True):
        """
        Load up and arrange the drop shadow
        """
        assert self.notify.debugStateCall(self)
        # First, protect this function from being called twice by
        # removing the old ones first.
        self.deleteDropShadow()

        # This will be used by the shadow system to identify things
        # that might want to have projected shadows drawn.
        if hasGeomNode:
            self.getGeomNode().setTag('cam', 'caster')

        # make the object float above the shadow slightly
        # not necessarily a good idea for all avatars
        # self.getGeomNode().setZ(0.025)

        # load and prep the drop shadow
        dropShadow = loader.loadModel(self.shadowFileName)
        dropShadow.setScale(
            0.4)  # Slightly smaller to compensate for billboard

        dropShadow.flattenMedium()
        dropShadow.setBillboardAxis(2)  # slide the shadow towards the camera
        dropShadow.setColor(
            0.0, 0.0, 0.0, globalDropShadowGrayLevel, 1
        )  # override of 1 to prevent avatar.setColor() from affecting shadows.
        self.shadowPlacer = ShadowPlacer(base.shadowTrav, dropShadow,
                                         OTPGlobals.WallBitmask,
                                         OTPGlobals.FloorBitmask)
        self.dropShadow = dropShadow
        if not globalDropShadowFlag:
            self.dropShadow.hide()
        if self.getShadowJoint():
            dropShadow.reparentTo(self.getShadowJoint())
        else:
            self.dropShadow.hide()

        # Set the state of the shadow placers (in case someone set the
        # value before now):
        self.setActiveShadow(self.wantsActive)

        self.__globalDropShadowFlagChanged()
        self.__globalDropShadowGrayLevelChanged()

    def update(self):
        """This method is meant to be overriden."""
        # Toontown doesn't have self.update() for all shadowcasters
        # but initializeDropShadow calls it, so this prevents a crash.
        pass

    def deleteDropShadow(self):
        """
        Lose the drop shadows
        """
        assert self.notify.debugStateCall(self)
        if self.shadowPlacer:
            self.shadowPlacer.delete()
            self.shadowPlacer = None

        if self.dropShadow:
            self.dropShadow.removeNode()
            self.dropShadow = None

    def setActiveShadow(self, isActive=1):
        """
        Turn the shadow placement on or off.
        """
        assert self.notify.debugStateCall(self)

        isActive = isActive and self.wantsActive
        if (not globalDropShadowFlag):
            self.storedActiveState = isActive
        # changed logic to prevent crash (test remark 13203) - grw
        if self.shadowPlacer != None:
            isActive = isActive and globalDropShadowFlag
            if self.activeShadow != isActive:
                self.activeShadow = isActive
                if isActive:
                    self.shadowPlacer.on()
                else:
                    self.shadowPlacer.off()

    def setShadowHeight(self, shadowHeight):
        """
        Places the shadow at a particular height below the avatar (in
        effect, asserting that the avatar is shadowHeight feet above
        the ground).

        This is only useful when the active shadow is disabled via
        setActiveShadow(0).
        """
        assert self.notify.debugStateCall(self)
        if self.dropShadow:
            self.dropShadow.setZ(-shadowHeight)

    def getShadowJoint(self):
        assert self.notify.debugStateCall(self)
        if hasattr(self, "shadowJoint"):
            return self.shadowJoint
        shadowJoint = self.find('**/attachShadow')
        if shadowJoint.isEmpty():
            # We make a fresh NodePath that refers to the same node as
            # self, rather than assigning self directly--this will
            # prevent a cyclic Python reference.
            self.shadowJoint = NodePath(self)
        else:
            self.shadowJoint = shadowJoint
        return self.shadowJoint

    def hideShadow(self):
        assert self.notify.debugStateCall(self)
        self.dropShadow.hide()

    def showShadow(self):
        assert self.notify.debugStateCall(self)
        if not globalDropShadowFlag:
            self.dropShadow.hide()
        else:
            self.dropShadow.show()

    def __globalDropShadowFlagChanged(self):
        if (self.dropShadow != None):
            if (globalDropShadowFlag == 0):
                if (self.activeShadow == 1):
                    self.storedActiveState = 1
                    self.setActiveShadow(0)
            elif (self.activeShadow == 0):
                self.setActiveShadow(1)
            self.showShadow()

    def __globalDropShadowGrayLevelChanged(self):
        if (self.dropShadow != None):
            self.dropShadow.setColor(0.0, 0.0, 0.0, globalDropShadowGrayLevel,
                                     1)
コード例 #5
0
 def __init__(self, cTrav, shadowNodePath, wallCollideMask, floorCollideMask, name):
     ShadowPlacer.__init__(self, cTrav, shadowNodePath, wallCollideMask, floorCollideMask)
     self.name = name
コード例 #6
0
class ShadowCaster:
    notify = DirectNotifyGlobal.directNotify.newCategory('ShadowCaster')

    def __init__(self, squareShadow = False):
        if squareShadow:
            self.shadowFileName = 'phase_3/models/props/square_drop_shadow'
        else:
            self.shadowFileName = 'phase_3/models/props/drop_shadow'
        self.dropShadow = None
        self.shadowPlacer = None
        self.activeShadow = 0
        self.wantsActive = 1
        self.storedActiveState = 0
        if hasattr(base, 'wantDynamicShadows') and base.wantDynamicShadows:
            messenger.accept('globalDropShadowFlagChanged', self, self.__globalDropShadowFlagChanged)
            messenger.accept('globalDropShadowGrayLevelChanged', self, self.__globalDropShadowGrayLevelChanged)

    def delete(self):
        if hasattr(base, 'wantDynamicShadows') and base.wantDynamicShadows:
            messenger.ignore('globalDropShadowFlagChanged', self)
            messenger.ignore('globalDropShadowGrayLevelChanged', self)
        self.deleteDropShadow()
        self.shadowJoint = None

    def initializeDropShadow(self, hasGeomNode = True):
        self.deleteDropShadow()
        if hasGeomNode:
            self.getGeomNode().setTag('cam', 'caster')
        dropShadow = loader.loadModel(self.shadowFileName)
        dropShadow.setScale(0.4)
        dropShadow.flattenMedium()
        dropShadow.setBillboardAxis(2)
        dropShadow.setColor(0.0, 0.0, 0.0, globalDropShadowGrayLevel, 1)
        self.shadowPlacer = ShadowPlacer(base.shadowTrav, dropShadow, OTPGlobals.WallBitmask, OTPGlobals.FloorBitmask)
        self.dropShadow = dropShadow
        if not globalDropShadowFlag:
            self.dropShadow.hide()
        if self.getShadowJoint():
            dropShadow.reparentTo(self.getShadowJoint())
        else:
            self.dropShadow.hide()
        self.setActiveShadow(self.wantsActive)
        self.__globalDropShadowFlagChanged()
        self.__globalDropShadowGrayLevelChanged()

    def update(self):
        pass

    def deleteDropShadow(self):
        if self.shadowPlacer:
            self.shadowPlacer.delete()
            self.shadowPlacer = None
        if self.dropShadow:
            self.dropShadow.removeNode()
            self.dropShadow = None

    def setActiveShadow(self, isActive = 1):
        isActive = isActive and self.wantsActive
        if not globalDropShadowFlag:
            self.storedActiveState = isActive
        if self.shadowPlacer != None:
            isActive = isActive and globalDropShadowFlag
            if self.activeShadow != isActive:
                self.activeShadow = isActive
                if isActive:
                    self.shadowPlacer.on()
                else:
                    self.shadowPlacer.off()

    def setShadowHeight(self, shadowHeight):
        if self.dropShadow:
            self.dropShadow.setZ(-shadowHeight)

    def getShadowJoint(self):
        if hasattr(self, 'shadowJoint'):
            return self.shadowJoint
        shadowJoint = self.find('**/attachShadow')
        if shadowJoint.isEmpty():
            self.shadowJoint = NodePath(self)
        else:
            self.shadowJoint = shadowJoint
        return self.shadowJoint

    def hideShadow(self):
        self.dropShadow.hide()

    def showShadow(self):
        if not globalDropShadowFlag:
            self.dropShadow.hide()
        else:
            self.dropShadow.show()

    def __globalDropShadowFlagChanged(self):
        if self.dropShadow != None:
            if globalDropShadowFlag == 0:
                if self.activeShadow == 1:
                    self.storedActiveState = 1
                    self.setActiveShadow(0)
            elif self.activeShadow == 0:
                self.setActiveShadow(1)
            self.showShadow()

    def __globalDropShadowGrayLevelChanged(self):
        if self.dropShadow != None:
            self.dropShadow.setColor(0.0, 0.0, 0.0, globalDropShadowGrayLevel, 1)
コード例 #7
0
 def __init__(self, cTrav, shadowNodePath, wallCollideMask, floorCollideMask, name):
     ShadowPlacer.__init__(self, cTrav, shadowNodePath, wallCollideMask, floorCollideMask)
     self.name = name
コード例 #8
0
    def __init__(self, cr):
        self.cr = cr
        DistributedSmoothNode.__init__(self, cr)
        NodePath.__init__(self, 'Mickey')
        self.name = "Mickey"
        self.anim = ""
        self.chat = ""

        self.mickey = Actor(
            "phase_3/models/char/mickey-1200.bam", {
                "neutral": "phase_3/models/char/mickey-wait.bam",
                "walk": "phase_3/models/char/mickey-walk.bam",
                "run": "phase_3/models/char/mickey-run.bam",
                "left-start": "phase_3.5/models/char/mickey-left-start.bam",
                "left": "phase_3.5/models/char/mickey-left.bam",
                "right-start": "phase_3.5/models/char/mickey-right-start.bam",
                "right": "phase_3.5/models/char/mickey-right.bam"
            })
        self.mickeyEye = self.mickey.controlJoint(None, "modelRoot",
                                                  "joint_pupilR")
        self.mickeyEye.setY(0.025)
        self.mickey.reparentTo(self)
        self.mickey.setScale(1.25)

        for bundle in self.mickey.getPartBundleDict().values():
            bundle = bundle['modelRoot'].getBundle()
            earNull = bundle.findChild('sphere3')
            if not earNull:
                earNull = bundle.findChild('*sphere3')
            earNull.clearNetTransforms()

        for bundle in self.mickey.getPartBundleDict().values():
            charNodepath = bundle['modelRoot'].partBundleNP
            bundle = bundle['modelRoot'].getBundle()
            earNull = bundle.findChild('sphere3')
            if not earNull:
                earNull = bundle.findChild('*sphere3')
            ears = charNodepath.find('**/sphere3')
            if ears.isEmpty():
                ears = charNodepath.find('**/*sphere3')
            ears.clearEffect(CharacterJointEffect.getClassType())
            earRoot = charNodepath.attachNewNode('earRoot')
            earPitch = earRoot.attachNewNode('earPitch')
            earPitch.setP(40.0)
            ears.reparentTo(earPitch)
            earNull.addNetTransform(earRoot.node())
            ears.clearMat()
            ears.node().setPreserveTransform(ModelNode.PTNone)
            ears.setP(-40.0)
            ears.flattenMedium()
            ears.setBillboardAxis()

        self.shadow = loader.loadModel("phase_3/models/props/drop_shadow.bam")
        self.shadow.setScale(0.55)
        self.shadow.flattenMedium()
        self.shadow.setBillboardAxis(4)
        try:
            self.shadowPlacer = ShadowPlacer(base.cTrav, self.shadow,
                                             base.wall_mask, base.floor_mask)
            self.shadowPlacer.on()
        except:
            pass
        self.shadow.reparentTo(self)

        cs = CollisionSphere(0, 0, 0, 2)
        cnode = CollisionNode('mickeyCNode')
        cnode.addSolid(cs)
        rs = CollisionRay(0, 0, 2, 0, 0, -1)
        rnode = CollisionNode('mickeyRNode')
        rnode.addSolid(rs)
        self.cnp = self.attachNewNode(cnode)
        self.cnp.setZ(0.75)
        self.rnp = self.attachNewNode(rnode)
コード例 #9
0
class DistributedMickey(DistributedSmoothNode):
    def __init__(self, cr):
        self.cr = cr
        DistributedSmoothNode.__init__(self, cr)
        NodePath.__init__(self, 'Mickey')
        self.name = "Mickey"
        self.anim = ""
        self.chat = ""

        self.mickey = Actor(
            "phase_3/models/char/mickey-1200.bam", {
                "neutral": "phase_3/models/char/mickey-wait.bam",
                "walk": "phase_3/models/char/mickey-walk.bam",
                "run": "phase_3/models/char/mickey-run.bam",
                "left-start": "phase_3.5/models/char/mickey-left-start.bam",
                "left": "phase_3.5/models/char/mickey-left.bam",
                "right-start": "phase_3.5/models/char/mickey-right-start.bam",
                "right": "phase_3.5/models/char/mickey-right.bam"
            })
        self.mickeyEye = self.mickey.controlJoint(None, "modelRoot",
                                                  "joint_pupilR")
        self.mickeyEye.setY(0.025)
        self.mickey.reparentTo(self)
        self.mickey.setScale(1.25)

        for bundle in self.mickey.getPartBundleDict().values():
            bundle = bundle['modelRoot'].getBundle()
            earNull = bundle.findChild('sphere3')
            if not earNull:
                earNull = bundle.findChild('*sphere3')
            earNull.clearNetTransforms()

        for bundle in self.mickey.getPartBundleDict().values():
            charNodepath = bundle['modelRoot'].partBundleNP
            bundle = bundle['modelRoot'].getBundle()
            earNull = bundle.findChild('sphere3')
            if not earNull:
                earNull = bundle.findChild('*sphere3')
            ears = charNodepath.find('**/sphere3')
            if ears.isEmpty():
                ears = charNodepath.find('**/*sphere3')
            ears.clearEffect(CharacterJointEffect.getClassType())
            earRoot = charNodepath.attachNewNode('earRoot')
            earPitch = earRoot.attachNewNode('earPitch')
            earPitch.setP(40.0)
            ears.reparentTo(earPitch)
            earNull.addNetTransform(earRoot.node())
            ears.clearMat()
            ears.node().setPreserveTransform(ModelNode.PTNone)
            ears.setP(-40.0)
            ears.flattenMedium()
            ears.setBillboardAxis()

        self.shadow = loader.loadModel("phase_3/models/props/drop_shadow.bam")
        self.shadow.setScale(0.55)
        self.shadow.flattenMedium()
        self.shadow.setBillboardAxis(4)
        try:
            self.shadowPlacer = ShadowPlacer(base.cTrav, self.shadow,
                                             base.wall_mask, base.floor_mask)
            self.shadowPlacer.on()
        except:
            pass
        self.shadow.reparentTo(self)

        cs = CollisionSphere(0, 0, 0, 2)
        cnode = CollisionNode('mickeyCNode')
        cnode.addSolid(cs)
        rs = CollisionRay(0, 0, 2, 0, 0, -1)
        rnode = CollisionNode('mickeyRNode')
        rnode.addSolid(rs)
        self.cnp = self.attachNewNode(cnode)
        self.cnp.setZ(0.75)
        self.rnp = self.attachNewNode(rnode)

    def mickeyCollisions(self):
        self.cnp.setCollideMask(BitMask32(0))
        self.cnp.node().setFromCollideMask(CIGlobals.WallBitmask)
        self.rnp.setCollideMask(BitMask32(0))
        self.rnp.node().setFromCollideMask(CIGlobals.FloorBitmask)

        ss = CollisionSphere(0, 0, 0, 10)
        snode = CollisionNode('mickeySNode')
        snode.addSolid(ss)
        self.snp = self.attachNewNode(snode)
        self.snp.setZ(0.75)
        self.snp.setCollideMask(BitMask32(0))
        self.snp.node().setFromCollideMask(CIGlobals.EventBitmask)

        pusher = CollisionHandlerPusher()
        pusher.setInPattern("%in")
        pusher.addCollider(self.cnp, self)
        floor = CollisionHandlerFloor()
        floor.setInPattern("%in")
        floor.addCollider(self.rnp, self)
        event = CollisionHandlerEvent()
        event.setInPattern("%fn-into")
        event.setOutPattern("%fn-out")
        base.cTrav.addCollider(self.cnp, pusher)
        base.cTrav.addCollider(self.rnp, floor)
        base.cTrav.addCollider(self.snp, event)

    def setName(self, name):
        self.name = name
        if name == "":
            return
        elif self.name == "minnie":
            self.name = "Minnie"
        try:
            self.nameTag.remove()
            del self.nameTag
        except:
            pass
        self.it = loader.loadFont("phase_3/models/fonts/ImpressBT.ttf")
        self.nameTag = DirectLabel(text=self.name,
                                   text_fg=(0.992188, 0.480469, 0.167969, 1.0),
                                   text_bg=(0.75, 0.75, 0.75, 0.5),
                                   text_wordwrap=8,
                                   text_decal=True,
                                   relief=None,
                                   parent=self)
        self.nameTag.setPos(0, 0, 5)
        self.nameTag.setBillboardPointEye()
        LS = LabelScaler()
        LS.resize(self.nameTag)

    def b_setName(self, name):
        self.d_setName(name)
        self.setName(name)

    def d_setName(self, name):
        self.sendUpdate("setName", [name])

    def setChat(self, chat):
        if chat == "":
            return
        self.nameTag.hide()
        try:
            self.bubble.remove()
            taskMgr.remove("RemoveMickeyChat-" + str(self.random_taskid))
        except:
            pass
        self.chat = chat
        self.it = loader.loadFont(CIGlobals.ToonFont,
                                  lineHeight=CIGlobals.ToonFontLineHeight)
        b = loader.loadTexture("phase_3/maps/chatbubble.jpg",
                               "phase_3/maps/chatbubble_a.rgb")

        self.balloon_sfx = loader.loadSfx(
            "phase_3/audio/sfx/GUI_balloon_popup.mp3")
        self.balloon_sfx.play()

        self.dial = loader.loadSfx("phase_3/audio/dial/mickey.wav")

        self.dial.play()

        self.box = loader.loadModel(CIGlobals.ChatBubble)
        self.ChatBalloon = ChatBalloon(self.box)
        LS = LabelScaler()
        self.bubble = self.ChatBalloon.generate(chat, self.it)
        LS.resize(self.bubble)
        self.bubble.reparentTo(self)
        self.bubble.setZ(self.nameTag.getZ() - 0.3)
        self.bubble.setBillboardPointEye()
        self.random_taskid = random.randint(
            0,
            10000000000000000000000000000000000000000000000000000000000000000000000
        )
        taskMgr.doMethodLater(7, self.delChat,
                              "RemoveMickeyChat-" + str(self.random_taskid))

    def delChat(self, task):
        self.chat = ""
        self.nameTag.show()
        self.bubble.remove()
        return task.done

    def b_setChat(self, chat):
        self.d_setChat(chat)
        self.setChat(chat)

    def d_setChat(self, chat):
        self.sendUpdate("setChat", [chat])

    def getChat(self):
        return self.chat

    def setAnimState(self, anim):
        self.anim = anim
        if "start" in anim:
            self.mickey.play(anim)
        self.mickey.loop(anim)

    def b_setAnimState(self, anim):
        self.d_setAnimState(anim)
        self.setAnimState(anim)

    def d_setAnimState(self, anim):
        self.sendUpdate("setAnimState", [anim])

    def getAnimState(self):
        return self.anim

    def announceGenerate(self):
        DistributedSmoothNode.announceGenerate(self)

        self.reparentTo(render)

    def generate(self):
        DistributedSmoothNode.generate(self)

        self.activateSmoothing(True, False)
        self.startSmooth()

    def disable(self):
        self.stopSmooth()
        self.detachNode()
        DistributedSmoothNode.disable(self)

    def delete(self):
        self.mickey = None
        DistributedSmoothNode.delete(self)