Beispiel #1
0
    def loadActor(self):
        if self.actor:
            self.actor.cleanup()
            
        self.actor = Actor('models/ralph',
                           {'walk' : 'models/ralph-walk',
                            'run' : 'models/ralph-run'})
        self.actor.reparentTo(self)
        self.actor.setScale(.2)

        # Setup a really simple nametag so we can know it's name.
        self.nameText = TextNode('%d-nameText' % self.doId)
        self.nameText.setText(self.name)
        self.nameText.setAlign(self.nameText.A_center)
        self.nameNP = self.attachNewNode(self.nameText)
        self.nameNP.setScale(.25)
        self.nameNP.setPos(0, 0, 1.2)
        self.nameNP.setBillboardPointEye()
        self.chatText = TextNode('%d-chatText' % self.doId)
        self.chatText.setText(self.chat)
        self.chatText.setAlign(self.chatText.A_center)
        self.chatText.setTextColor(0.5, 0.5, 1, 1)
        self.chatNP = self.attachNewNode(self.chatText)
        self.chatNP.setScale(.35)
        self.chatNP.setPos(0, 0, 1.6)
        self.chatNP.setBillboardPointEye()
    def Game_Point(self):
	
		
	self.ignore("arrow_down")	
	self.ignore("arrow_up")
	self.ignore("arrow_down-repeat")
	self.ignore("arrow_up-repeat")
	#self.text1 = addInstructions(0.5,"Is this Recyclable")
	self.text1 = TextNode('t1')
	self.text1.setText("is This  Recyclable")
	self.text1.setTextColor(0,0,0,1)
	self.textNodePath1 = aspect2d.attachNewNode(self.text1)
	self.textNodePath1.setScale(0.07)
	self.textNodePath1.setPos(-0.1,-0.1,0.1) 	
	#text1.setTextColor(1,1,1)
	self.text1.setFrameColor(1, 0, 0, 1)
	self.text1.setFrameAsMargin(0.2, 0.2, 0.1, 0.1)	

	self.text2 = TextNode('t2')
        self.text2.setText("Y/N")
        self.text2.setTextColor(0,0,0,1)
	self.textNodePath2 = aspect2d.attachNewNode(self.text2)
        self.textNodePath2.setScale(0.07)
        self.textNodePath2.setPos(0,0,0) 
	#textNodePath2.setTextColor(1,1,1) 
        self.text2.setFrameColor(1, 0, 0, 1)
        self.text2.setFrameAsMargin(0.2, 0.2, 0.1, 0.1)
	self.accept('y',self.answer,[0])
        self.accept('n',self.answer,[1])
Beispiel #3
0
    def setupCoins2(self):
        # display coins = 0
        textN = TextNode('coin-score')
        textN.setText(str("Coins: " + str(self.coinsCollected2)))
        textN.setSlant(0.1)
        textNodePath = self.aspect2d.attachNewNode(textN)
        textNodePath.setPos(0, 0.95, 0.9)
        textNodePath.setScale(0.08)
        randNum = random.sample(range(0, 1500, 200), 6)

        # coins
        for i in range(6):
            randX = random.uniform(-3.0, 3.2)
            randY = float(randNum[i])
            shape = BulletSphereShape(0.3)
            coinNode = BulletGhostNode('Coin-' + str(i))
            coinNode.addShape(shape)
            np = self.render.attachNewNode(coinNode)
            np.setCollideMask(BitMask32.allOff())
            np.setPos(randX, randY, 2)

            # Adding sphere model
            sphereNp = loader.loadModel('models/smiley.egg')
            sphereNp_tex = loader.loadTexture("models/sky/coin_2_tex.jpg")
            sphereNp.setTexture(sphereNp_tex, 1)
            sphereNp.reparentTo(np)
            sphereNp.setScale(0.45)
            sphereNp.hprInterval(2.5, Vec3(360, 0, 0)).loop()

            self.world2.attachGhost(coinNode)
            self.coins2.append(coinNode)
            print "node name:" + str(coinNode.getName())
Beispiel #4
0
class FastTextNode(DebugObject):

    """ Interface for the Panda3D TextNode. """

    def __init__(self, font="Data/Font/Roboto-Bold.ttf", pixel_size=16, align="left",
                 pos=Vec2(0), color=Vec3(1), parent=None):
        self._node = TextNode('FTN')
        self._node.set_text("Text")
        self._node.set_align(getattr(TextNode, "A_" + align))
        self._node.set_text_color(color.x, color.y, color.z, 1)

        if parent is None:
            parent = Globals.base.aspect2d

        self._nodepath = parent.attach_new_node(self._node)
        self._nodepath.set_scale(pixel_size * 2.0 / float(Globals.base.win.get_y_size()))
        self._nodepath.set_pos(pos.x, 0, pos.y)

        font = Globals.loader.loadFont(font)
        font.set_outline(Vec4(0, 0, 0, 0.78), 1.6, 0.37)
        font.set_scale_factor(1.0)
        font.set_texture_margin(int(pixel_size / 4.0 * 2.0))
        font.set_bg(Vec4(0, 0, 0, 0))

        self._node.set_font(font)

    def set_text(self, text):
        self._node.set_text(text)
 def initFishStaminaBar(self):
     self.legendaryGui = loader.loadModel('models/minigames/pir_m_gam_fsh_legendaryGui')
     self.iconBaseFrame = DirectFrame(relief = None, state = DGG.DISABLED, pos = (0, 0, 0), sortOrder = 30, image = self.legendaryGui.find('**/pir_t_gui_fsh_fishPortraitFrame'), image_scale = 0.17999999999999999, image_pos = (0, 0, 0))
     self.iconBaseFrame.setTransparency(TransparencyAttrib.MAlpha)
     self.fishUINodePath = NodePath(self.iconBaseFrame)
     self.fishUINodePath.setPos(-0.29999999999999999, 0.0, 0.82999999999999996)
     self.fishUINodePath.reparentTo(hidden)
     self.iconCard = loader.loadModel('models/gui/treasure_gui')
     self.iconBaseFrame.iconImage = OnscreenImage(parent = self.iconBaseFrame, image = self.iconCard.find('**/%s*' % CollectionMap.Assets[self.myData['id']]), scale = 0.34999999999999998, hpr = (0, 0, 0), pos = (0.0, 0, 0.0))
     self.fishNameLabel = TextNode('fishNameLabel')
     name = self.getName().split('_')
     self.fishNameLabel.setText(name[0])
     self.fishNameLabel.setTextColor(1.0, 1.0, 1.0, 1.0)
     self.fishNameLabelNodePath = NodePath(self.fishNameLabel)
     self.fishNameLabelNodePath.setPos(0.29999999999999999, 0, 0.040000000000000001)
     self.fishNameLabelNodePath.setScale(0.044999999999999998)
     self.fishNameLabelNodePath.reparentTo(self.iconBaseFrame)
     self.fishStaminaBar = DirectWaitBar(parent = self.iconBaseFrame, relief = DGG.FLAT, state = DGG.DISABLED, range = 100, value = 0, sortOrder = 20, frameColor = (0, 0, 0, 1.0), pos = (0.070000000000000007, 0.0, -0.014999999999999999), hpr = (0, 0, 0), frameSize = (0, 0.71999999999999997, 0, 0.028000000000000001))
     self.fishStaminaBar['value'] = self.staminaValue
     self.fishStaminaBar['barColor'] = FishingGlobals.fishingStaminaBarColor[int((self.staminaValue / 100.0) * (len(FishingGlobals.fishingStaminaBarColor) - 1))]
     self.fishStaminaValueLabel = TextNode('fishStaminaValueLabel')
     self.fishStaminaValueLabel.setText(str(self.staminaValue) + '//' + str(self.staminaValue))
     self.fishStaminaValueLabel.setTextColor(1.0, 1.0, 1.0, 1.0)
     self.fishStaminaValueLabelNodePath = NodePath(self.fishStaminaValueLabel)
     self.fishStaminaValueLabelNodePath.setPos(0.66000000000000003, 0, -0.059999999999999998)
     self.fishStaminaValueLabelNodePath.setScale(0.044999999999999998)
     self.fishStaminaValueLabelNodePath.reparentTo(self.iconBaseFrame)
     self.fishStaminaBarFrame = DirectLabel(parent = self.iconBaseFrame, relief = None, state = DGG.DISABLED, frameColor = (1, 1, 1, 0.10000000000000001), pos = (0.44, 0.0, 0.0), hpr = (0, 0, 0), sortOrder = 25, image = self.legendaryGui.find('**/pir_t_gui_fsh_staminaBarForeground'), image_scale = (1.0, 0.0, 0.050000000000000003), image_pos = (0.0, 0.0, 0.0), image_hpr = (0.0, 0.0, 0.0))
     self.fishStaminaBarFrame.setTransparency(TransparencyAttrib.MAlpha)
     self.fishStaminaBarFrame.setDepthTest(True)
     self.fishStaminaBarFrame.setDepthWrite(True)
Beispiel #6
0
    def renderClickableModel(self, showModel=True, showName=False):
        ''' Render just the clickable (reference) model '''
        # Hide all non clickable objects
        self.nonClickable.clearColor()
        self.nonClickable.hide()
        # Show the clickable model with the original texture and color
        self.clickableModel.clearColor()
        self.clickableModel.clearColorScale()
        if showModel:
            # Place it in front of the user, face-to-face (we try to randomly parametrize the position and orientation of the reference model but in a way that the user can clearly see it face-to-face)
            self.clickableModel.setPos(0,40,0)
            self.clickableModel = self.normalizeModelSize(self.clickableModel, self.minModelSize, self.maxModelSize, self.clickableModelSize) # set size (normalize size and set a random size in the normalized range)
            self.clickableModel.setHpr(random.uniform(-45, 45), random.uniform(-15, 15), 0)
            self.clickableModel.setColorScale(random.random(), random.random(), random.random(), 1.0)
        else:
            self.clickable.hide()

        if showName:
            if not hasattr(self, 'clickableText') or self.clickableText != self.clickableModelName:
                if hasattr(self, 'clickableText'):
                    self.clickableText.remove()
                text = TextNode('reference model name')
                text.setText(self.clickableModelName)
                text.setAlign(TextNode.ACenter)
                self.clickableText = render2d.attachNewNode(text)
                self.clickableText.setScale( 0.2 )
                self.clickableText.setPos( 0, 0, -0.8 )
 def __init__(self, w, h, locationId = LocationIds.PORT_ROYAL_ISLAND):
     GuiPanel.GuiPanel.__init__(self, '', w, h, True)
     self.card = loader.loadModel('models/gui/pir_m_gui_fsh_legendaryScreen')
     self.storyImageCard = loader.loadModel('models/minigames/pir_m_gam_fsh_legendaryGui')
     self.UICompoments = { }
     self.setPos(-1.1499999999999999, 0.0, -0.59999999999999998)
     self['geom'] = self.card.find('**/background')
     self['geom_pos'] = (0.57999999999999996, 0.0, 0.63)
     self['geom_scale'] = (0.94999999999999996, 0.0, 0.84999999999999998)
     self.coinImage = OnscreenImage(parent = self, image = self.card.find('**/coin'), scale = 0.90000000000000002, hpr = (0, 0, 0), pos = (0.84999999999999998, 0, 0.84999999999999998))
     self.titleTextNode = TextNode('legendPanelTitle')
     self.titleTextNode.setText(PLocalizer.LegendSelectionGui['panelTitle'])
     self.titleTextNode.setFont(PiratesGlobals.getPirateFont())
     self.titleTextNode.setTextColor(0.87, 0.81999999999999995, 0.54000000000000004, 0.90000000000000002)
     self.titleTextNodePath = NodePath(self.titleTextNode)
     self.titleTextNodePath.setPos(0.65000000000000002, 0.0, 1.2)
     self.titleTextNodePath.setScale(0.070000000000000007)
     self.titleTextNodePath.reparentTo(self)
     self.introTextNode = TextNode('legendaryIntroTextNode')
     self.introTextNode.setText(PLocalizer.LegendSelectionGui['legendIntro'])
     self.introTextNode.setWordwrap(14.0)
     self.introTextNode.setTextColor(0.90000000000000002, 0.80000000000000004, 0.46999999999999997, 0.90000000000000002)
     self.introTextNodePath = NodePath(self.introTextNode)
     self.introTextNodePath.setPos(0.59999999999999998, 0.0, 0.5)
     self.introTextNodePath.setScale(0.042000000000000003)
     self.introTextNodePath.reparentTo(self)
     self.buttonRootNode = NodePath('button_RootNode')
     self.buttonRootNode.reparentTo(self)
     self.buttonRootNode.setPos(-0.080000000000000002, 0.0, 1.1499999999999999)
     self.iconCard = loader.loadModel('models/gui/treasure_gui')
     self.legendSelectionButtons = { }
     btnGeom = (self.card.find('**/fishButton/idle'), self.card.find('**/fishButton/idle'), self.card.find('**/fishButton/over'))
     for i in range(len(FishingGlobals.legendaryFishData)):
         fishName = FishingGlobals.legendaryFishData[i]['name']
         fishId = FishingGlobals.legendaryFishData[i]['id']
         assetsKey = CollectionMap.Assets[fishId]
         pos_x = 0.29999999999999999
         pos_z = 0.0 - i * 0.25
         button = GuiButton(parent = self.buttonRootNode, text = (fishName, fishName, fishName, fishName), text0_fg = (0.42999999999999999, 0.28999999999999998, 0.19, 1.0), text1_fg = (0.42999999999999999, 0.28999999999999998, 0.19, 1.0), text2_fg = (0.42999999999999999, 0.28999999999999998, 0.19, 1.0), text3_fg = (0.42999999999999999, 0.28999999999999998, 0.19, 1.0), text_scale = 0.035000000000000003, text_pos = (0.037999999999999999, -0.0050000000000000001), pos = (pos_x, 0, pos_z), hpr = (0, 0, 0), scale = 1.5, image = btnGeom, image_pos = (0, 0, 0), image_scale = 0.69999999999999996, sortOrder = 2, command = self.buttonClickHandle, extraArgs = [
             fishId,
             assetsKey,
             locationId])
         button.icon = OnscreenImage(parent = button, image = self.iconCard.find('**/%s*' % assetsKey), scale = 0.34999999999999998, hpr = (0, 0, 0), pos = (-0.123, 0, 0.0050000000000000001))
     
     self.legendPanel = GuiPanel.GuiPanel('', 2.6000000000000001, 1.8999999999999999, True)
     self.legendPanel.setPos(-1.3, 0.0, -0.94999999999999996)
     self.legendPanel.background = OnscreenImage(parent = self.legendPanel, scale = (2.3999999999999999, 0, 1.8), image = self.storyImageCard.find('**/pir_t_gui_fsh_posterBackground'), hpr = (0, 0, 0), pos = (1.3, 0, 0.94999999999999996))
     self.legendPanel.storyImage = OnscreenImage(parent = self.legendPanel, scale = 1, image = self.card.find('**/coin'), hpr = (0, 0, 0), pos = (1.8, 0, 1))
     self.storyTextNode = TextNode('storyTextNode')
     self.storyTextNode.setText('')
     self.storyTextNode.setWordwrap(19.0)
     self.storyTextNode.setTextColor(0.23000000000000001, 0.089999999999999997, 0.029999999999999999, 1.0)
     self.storyTextNodePath = NodePath(self.storyTextNode)
     self.storyTextNodePath.setPos(0.33000000000000002, 0.0, 1.6699999999999999)
     self.storyTextNodePath.setScale(0.050000000000000003)
     self.storyTextNodePath.reparentTo(self.legendPanel)
     self.callBack = None
     self.legendPanel.hide()
Beispiel #8
0
 def fontHasCharacters(name, font = font):
     if font:
         tn = TextNode('NameCheck')
         tn.setFont(font)
         for c in name:
             # Define c as unicode
             if not tn.hasCharacter(unichr(ord(c))):
                 notify.info('name contains bad char: %s' % TextEncoder().encodeWtext(c))
                 return OTPLocalizer.NCBadCharacter % TextEncoder().encodeWtext(c)
 def _show(self, ctb, identifier, parentnode):
     if self.node is not None: self.node.removeNode()
     tnode = TextNode(identifier)
     tnode.setText(ctb.text)
     r, g, b, a = ctb.textcolor.r / 255.0, ctb.textcolor.g / 255.0, ctb.textcolor.b / 255.0, ctb.textcolor.a / 255.0
     tnode.setTextColor(r, g, b, a)
     node = NodePath(tnode)
     self._scale(tnode, node)
     node.reparentTo(parentnode)
     self.node = node
Beispiel #10
0
 def draw(self):
     # stuffandeer stuffandeer otus
     for card in self.hand:
         textn = TextNode(card.name)
         textn.setText(card.name)
         textnp = card.model.attachNewNode(textn)
         textnp.setScale(0.3)
         textnp.setPos(card.model, -2, 0, 1)
         textnp.setHpr(card.model, 0, -90, -90)
         textn.setAlign(TextNode.ACenter)
Beispiel #11
0
    def draw_mstr(self, mstr, box, identifier="", parameters=None):
        self.aspect = True
        if box.mode == "pixels":
            parent2d = self.get_parent_pixel2d()
        elif box.mode == "standard":
            parent2d = self.get_parent_render2d()
        elif box.mode == "aspect":
            parent2d = self.get_parent_aspect2d()

        tnode = TextNode(identifier)
        tnode.setText(mstr.value)
        # TODO: use more parameters
        if hasattr(parameters, "cardcolor"):
            tnode.setCardColor(*parameters.cardcolor)
            tnode.setCardAsMargin(0, 0, 0, 0)
            tnode.setCardDecal(True)
        if hasattr(parameters, "aspect"):
            self.aspect = parameters.aspect

        node = NodePath(tnode)
        self._scale(tnode, node, box.x, box.y, box.sizex, box.sizey)
        node.setBin("fixed", self.get_next_sortid())
        node.setDepthTest(False)
        node.setDepthWrite(False)
        node.reparentTo(parent2d)
        return (mstr, node, tnode, box, parameters)
Beispiel #12
0
    def drawBuilding(self, building, field):
        model = self.loader.loadModel('models/house')
        # model.setScale(0.05)
        model.reparentTo(field.model)
        building.model = model
        self.modelToBuilding[model.getKey()] = building
        player = self.game.currentPlayer()
        model.setTag('clickable', 'true')
        cs = CollisionSphere(0, 0, 0, 2)
        cnodePath = model.attachNewNode(CollisionNode('cnode'))
        cnodePath.node().addSolid(cs)
        # cnodePath.show()

        col = 256 * int(player.color)
        # set building title
        title = TextNode(str(building.model.getKey()) + '_title')
        title.setText(building.building)
        title.setCardColor(col, col, col, 1)
        title.setCardAsMargin(0.1, 0.1, 0.1, 0.1)
        title.setCardDecal(True)
        titleNode = self.render.attachNewNode(title)
        titleNode.reparentTo(building.model)
        titleNode.setScale(1.5)
        titleNode.setPos(0, 0, 3)
        titleNode.setBillboardPointEye()
 def start(self):
     self._credits_node = aspect2d.attachNewNode("credits-node")
     text = TextNode('node name')
     text.setText(" A solar storm hits a moon base.\n Some vital systems are breaking.\n Get close to repair them before failure\nof four simultaneously, because this\ndestroy the base.")
     
     textNodePath = self._credits_node.attachNewNode(text)
     textNodePath.setScale(0.07)
     textNodePath.setPos((0.0, 0.0, 0.0))
     
     DirectButton(text = ("Back", "Back", "Back", "Back"),
         pos=(0, 0, -0.8), scale=.15, command=self._butBack, parent=self._credits_node)
Beispiel #14
0
    def createActor(self, render, username, x, y, z, h):
        actor = PlayerObject(render, username, x, y, z, h)

        # Displays username above Ralph character
        nameplate = TextNode('textNode username_' + str(username))
        nameplate.setText(username)
        npNodePath = actor.actor.attachNewNode(nameplate)
        npNodePath.setScale(1.0)
        npNodePath.setBillboardPointEye()
        npNodePath.setZ(8.0)

        return actor
 def generate(self):
     DistributedObject.announceGenerate(self)
     self.trolleyStation = self.cr.playGame.hood.loader.geom.find('**/prop_trolley_station_DNARoot')
     self.trolleyCar = self.trolleyStation.find('**/trolley_car')
     self.trolleyKey = self.trolleyStation.find('**/key')
     tn = TextNode('trolleycountdowntext')
     tn.setFont(CIGlobals.getMickeyFont())
     tn.setTextColor(1, 0, 0, 1)
     self.countdownText = self.trolleyStation.attachNewNode(tn)
     self.countdownText.setScale(3.0)
     self.countdownText.setPos(14.58, 10.77, 11.17)
     self.acceptOnce('entertrolley_sphere', self.__handleTrolleyTrigger)
Beispiel #16
0
    def drawFigures(self):
        for player in self.game.players:
            for figure in player.figures:
                if hasattr(figure, 'model'):
                    continue
                if type(figure) == Ship:
                    field = figure.field
                    figure.model = self.loader.loadModel('models/ship')
                    figure.model.reparentTo(field.model)
                    cs = CollisionSphere(1.5, 0, 1, 1.3)
                    cnodePath = figure.model.attachNewNode(
                        CollisionNode('cnode'))
                    cnodePath.node().addSolid(cs)
                    # cnodePath.show()
                    cs = CollisionSphere(0, 0, 1.4, 1.3)
                    cnodePath = figure.model.attachNewNode(
                        CollisionNode('cnode'))
                    cnodePath.node().addSolid(cs)
                    # cnodePath.show()
                    cs = CollisionSphere(-1.8, 0, 1, 1)
                    cnodePath = figure.model.attachNewNode(
                        CollisionNode('cnode'))
                    cnodePath.node().addSolid(cs)
                    # cnodePath.show()
                    figure.model.setScale(1.4)
                    figure.model.setHpr(90, 0, 0)
                    # figure.model.setTag('highlightable', 'true')
                    figure.model.setTag('clickable', 'true')
                    self.modelToFigure[figure.model.getKey()] = figure
                else:
                    field = figure.field
                    figure.model = self.loader.loadModel('models/warrior100')
                    figure.model.reparentTo(field.model)
                    cs = CollisionSphere(0, -.35, 7, 1)
                    cnodePath = figure.model.attachNewNode(
                        CollisionNode('cnode'))
                    cnodePath.node().addSolid(cs)
                    figure.model.setScale(0.35)
                    figure.model.setTag('highlightable', 'true')
                    figure.model.setTag('clickable', 'true')
                    self.modelToFigure[figure.model.getKey()] = figure

                col = 256 * int(player.color)
                # set figure title
                title = TextNode(str(figure.model.getKey()) + '_title')
                title.setText(type(figure).__name__)
                title.setCardColor(col, col, col, 1)
                title.setCardAsMargin(0.1, 0.1, 0.1, 0.1)
                title.setCardDecal(True)
                titleNode = self.render.attachNewNode(title)
                titleNode.reparentTo(figure.model)
                titleNode.setScale(3)
                titleNode.setPos(0, 3, 10)
                if type(figure) == Ship:
                    titleNode.setScale(1.5)
                    titleNode.setPos(-1.5, 0, 3)
                titleNode.setBillboardPointEye()
Beispiel #17
0
class gameText(DirectObject):
	'''This class creates texts that will be part of the HUD of the game
	'''
	def __init__(self, name, content, position, scale):
		#Writing our gameText and giving it a name(to help identifying which text is this)
		self.name = TextNode('%s'%name)
		self.name.setText("%s"%content)
		#now this gameText is child of hudTexts node
		self.textNodePath = hudTexts.attachNewNode(self.name)
		#positioning and scaling our gameText
		self.position = Vec3(*position)
		self.textNodePath.setX(self.position[0]), self.textNodePath.setZ(self.position[2])
		self.textNodePath.setScale(scale)
Beispiel #18
0
def getTextSize(txt, style):
	tn = TextNode(txt)
	tn.setText(txt)
	tn.setFont(loader.loadFont(style['font']))
	tn.setSlant(style['slant'])
	#tn.setFont(style['font'])
	fontSize = style['font-size']
	lineHeight = tn.getLineHeight()
	f = tn.getFrameActual()
	return (tn.getWidth()*fontSize,\
		(f[3]-f[2])*fontSize,\
		lineHeight*fontSize,\
		(0, f[1]*fontSize, f[2]*fontSize, f[3]*fontSize))
	def addText(self,name,text,xpos,ypos,r,g,b,align):
		textNode=TextNode(name)
		textNode.setText(text)
		textNode.setFont(self.font)
		textNode.setTextColor(r,g,b,1.0)
		textNode.setAlign(align)
		textNodePath=self.containerNode.attachNewNode(textNode)
		textNodePath.setScale(self.fontScale)
		textNodePath.setPos((2.0/self.characterWidth*xpos)-1,0.0,(2.0/self.characterHeight*ypos)-1) 
		return textNode
	def initializePromptTextPart1(self):
		self.timerText = TextNode('timer')
		self.timerText.setText("Time:" + "0" + str(self.timer))
		self.timerText.setShadow(0.05, 0.05)
		self.timerTextNodePath = aspect2d.attachNewNode(self.timerText)
		self.timerTextNodePath.setScale(0.07)
		self.timerTextNodePath.setPos(1.2,0,0.9)

		self.saveTimeText = TextNode('would you like to save?')
		self.saveTimeText.setText('')#
		self.saveTimeText.setShadow(0.05, 0.05)
		self.saveTimeTextNodePath = aspect2d.attachNewNode(self.saveTimeText)
		self.saveTimeTextNodePath.setScale(0.07)
		self.saveTimeTextNodePath.setPos(1.1, 0, 0.8)
	def initializePressedDownKeysPart1(self):
		self.wText = TextNode('w')
		self.wText.setText("w")
		self.wText.setShadow(0.05, 0.05)
		self.wTextNodePath = aspect2d.attachNewNode(self.wText)
		self.wTextNodePath.setScale(0.07)
		self.wTextNodePath.setPos(-1.6,0,-0.75)

		self.sText = TextNode('s')
		self.sText.setText("s")
		self.sText.setShadow(0.05, 0.05)
		self.sTextNodePath = aspect2d.attachNewNode(self.sText)
		self.sTextNodePath.setScale(0.07)
		self.sTextNodePath.setPos(-1.35,0,-0.75)
	def initializePressedDownKeysPart3(self):
		self.upText = TextNode('Up')
		self.upText.setText("Up")
		self.upText.setShadow(0.05, 0.05)
		self.upTextNodePath = aspect2d.attachNewNode(self.upText)
		self.upTextNodePath.setScale(0.07)
		self.upTextNodePath.setPos(-1.6,0,-0.85)

		self.downText = TextNode('Down')
		self.downText.setText("Down")
		self.downText.setShadow(0.05, 0.05)
		self.downTextNodePath = aspect2d.attachNewNode(self.downText)
		self.downTextNodePath.setScale(0.07)
		self.downTextNodePath.setPos(-1.35,0,-0.85)
	def loadPickModelTextPart1(self):
		self.skin1Text = TextNode('skin1')
		self.skin1Text.setText("[1] - Fighter")
		self.skin1Text.setShadow(0.05, 0.05)
		self.skin1TextNodePath = aspect2d.attachNewNode(self.skin1Text)
		self.skin1TextNodePath.setScale(0.07)
		self.skin1TextNodePath.setPos(-1.3,0,0.3)	

		self.skin2Text = TextNode('skin2')
		self.skin2Text.setText("[2] - Boeing707")
		self.skin2Text.setShadow(0.05, 0.05)
		self.skin2TextNodePath = aspect2d.attachNewNode(self.skin2Text)
		self.skin2TextNodePath.setScale(0.07)
		self.skin2TextNodePath.setPos(-0.1,0,0.3)	
	def initializePressedDownKeysPart4(self):
		self.rightText = TextNode('Left')
		self.rightText.setText("Left")
		self.rightText.setShadow(0.05, 0.05)
		self.rightTextNodePath = aspect2d.attachNewNode(self.rightText)
		self.rightTextNodePath.setScale(0.07)
		self.rightTextNodePath.setPos(-1.1,0,-0.85)	

		self.leftText = TextNode('Right')
		self.leftText.setText("Right")
		self.leftText.setShadow(0.05, 0.05)
		self.leftTextNodePath = aspect2d.attachNewNode(self.leftText)
		self.leftTextNodePath.setScale(0.07)
		self.leftTextNodePath.setPos(-0.85,0,-0.85)		
	def loadPickModelTextPart3(self):
		self.skin5Text = TextNode('skin5')
		self.skin5Text.setText("[5] - Seeker")
		self.skin5Text.setShadow(0.05, 0.05)
		self.skin5TextNodePath = aspect2d.attachNewNode(self.skin5Text)
		self.skin5TextNodePath.setScale(0.07)
		self.skin5TextNodePath.setPos(-0.1,0,-0.5)	

		self.skin6Text = TextNode('skin6')
		self.skin6Text.setText("[6] - Jeep")
		self.skin6Text.setShadow(0.05, 0.05)
		self.skin6TextNodePath = aspect2d.attachNewNode(self.skin6Text)
		self.skin6TextNodePath.setScale(0.07)
		self.skin6TextNodePath.setPos(1,0,-0.5)	
	def initializePressedDownKeysPart2(self):
		self.aText = TextNode('a')
		self.aText.setText("a")
		self.aText.setShadow(0.05, 0.05)
		self.aTextNodePath = aspect2d.attachNewNode(self.aText)
		self.aTextNodePath.setScale(0.07)
		self.aTextNodePath.setPos(-1.1,0,-0.75)	

		self.dText = TextNode('d')
		self.dText.setText("d")
		self.dText.setShadow(0.05, 0.05)
		self.dTextNodePath = aspect2d.attachNewNode(self.dText)
		self.dTextNodePath.setScale(0.07)
		self.dTextNodePath.setPos(-0.85,0,-0.75)
Beispiel #27
0
    def createActor(self, id, position, gameclient):
        actor = DynObject(render, id, position, gameclient)
        actor.motion_controller = NetworkObjectController(actor)
        self.addObject(actor)

        text = TextNode('node name_'+str(id))
        text.setText('Ralph_'+str(id))
        textNodePath = actor.actor.attachNewNode(text)
        textNodePath.setScale(1.0)        
        textNodePath.setBillboardPointEye()
        textNodePath.setZ(8.0)
        # textNodePath.setX(2.0)

        return actor
	def loadPickModelTextPart2(self):

		self.skin3Text = TextNode('skin3')
		self.skin3Text.setText("[3] - R2D2")
		self.skin3Text.setShadow(0.05, 0.05)
		self.skin3TextNodePath = aspect2d.attachNewNode(self.skin3Text)
		self.skin3TextNodePath.setScale(0.07)
		self.skin3TextNodePath.setPos(1,0,0.3)	

		self.skin4Text = TextNode('skin4')
		self.skin4Text.setText("[4] - Blimp")
		self.skin4Text.setShadow(0.05, 0.05)
		self.skin4TextNodePath = aspect2d.attachNewNode(self.skin4Text)
		self.skin4TextNodePath.setScale(0.07)
		self.skin4TextNodePath.setPos(-1.3,0,-0.5)	
Beispiel #29
0
class GUI(object):

    """ Handles the gui elements like showing the current stage """

    def __init__(self, control):

        self.control = control
        self.gui_node = pixel2d.attach_new_node("GUI")
        self.gui_node.hide()
        self.gui_node.set_transparency(True)

        roboto_light = loader.loadFont("res/Roboto-Light.ttf")
        roboto_light.set_scale_factor(1)
        roboto_light.set_pixels_per_unit(120)

        self.text_stage = TextNode("TextStage")
        self.text_stage.set_text("Stage 1")
        self.text_stage.set_align(TextNode.A_left)
        self.text_stage.set_text_color(1, 1, 1, 1)
        self.text_stage.set_font(roboto_light)
        self.text_stage_np = self.gui_node.attach_new_node(self.text_stage)
        self.text_stage_np.set_scale(80.0)
        self.text_stage_np.set_pos(60, 0, -120)

        self.anim = None

    def show(self):
        self.gui_node.show()
        if self.anim is not None:
            self.anim.finish()
        self.anim = Sequence(
            LerpColorScaleInterval(self.gui_node, 0.2, Vec4(1), Vec4(1, 1, 1, 0), blendType="easeInOut")
        )
        self.anim.start()

    def hide(self):
        self.gui_node.hide()
        if self.anim is not None:
            self.anim.finish()
        self.anim = Sequence(
            LerpColorScaleInterval(self.gui_node, 0.2, Vec4(1, 1, 1, 0), Vec4(1), blendType="easeInOut")
        )
        self.anim.start()


    def set_stage(self, stage_nr):
        print(("Setting stage", stage_nr))

        Sequence(
            LerpColorScaleInterval(self.text_stage_np, 0.4, Vec4(1, 1, 1, 0), Vec4(1), blendType="easeInOut"),
            Func(lambda *args: self.text_stage.set_text("Stage " + str(stage_nr))),
            LerpColorScaleInterval(self.text_stage_np, 0.4, Vec4(1), Vec4(1, 1, 1, 0), blendType="easeInOut"),
        ).start()
Beispiel #30
0
    def __init__(self):
        # the tasktime the last sign in the textfield was written
        self.lastSign = 0.0
        # the sign that is actually written in the textfield
        self.currentSign = 0
        # the text to write in the textfield
        self.textfieldText = ""
        # stop will be used to check if the writing is finished or
        # somehow else stoped
        self.stop = False
        # the speed new letters are added to the text
        # the time, how long the text is shown after it is fully written
        self.showlength = 4

        # the textfield to put instructions hints and everything else, that
        # should be slowly written on screen and disappear after a short while
        self.textfield = TextNode('textfield')
        self.textfield.clearText()
        self.textfield.setShadow(0.005, 0.005)
        self.textfield.setShadowColor(0, 0, 0, 1)
        self.textfield.setWordwrap(base.a2dRight*2-0.4)
        self.textfield.setCardActual(
            -0.1, base.a2dRight*2-0.3,
            0.1, base.a2dBottom+0.5)
        self.textfield.setCardColor(0,0,0,0.45)
        self.textfield.setFlattenFlags(TextNode.FF_none)
        self.textfield.setTextScale(0.06)
        self.textfieldNodePath = aspect2d.attachNewNode(self.textfield)
        self.textfieldNodePath.setScale(1)
        self.textfieldNodePath.setPos(base.a2dLeft+0.2, 0, -0.4)

        self.hide()
Beispiel #31
0
class MyApp(ShowBase):
	def __init__(self, server):
		ShowBase.__init__(self)

		#the way the user interface can read held down buttons is by
		#setting the button to be true when it's pressed down, and then
		#it sets it back to false when it's released
		#I have a constant while loop that'll simply read the key dictionary
		#and act whenever one of the values reads True, or in this case 1
		self.keys = {"w": 0, "s": 0, "d": 0, "a":0,"u":0, "e":0,"r": 0,"l": 0}
		self.initPart2()

	#part 2 of the init, the first one got taken up by alot of comments

	def initPart2(self):
		#assigns all of the variables needed in the class
		self.defineVariables()

		self.loadEnvironments()
		
		self.camera.setPos(29,-20,2)
		# self.camera.setHpr(-123.333, 0, 0)
		self.loadModels()

		self.initializeKeys1()
		self.initializeKeys2()

		self.startThreads()

	#these are the data variables that are being sent by the server. so far,
	#I haven't displayed any of these variables, as I've noticed they cause
	#a fair amount of lag/delay, but I am implementing the gyroscope values

	def defineVariables(self):
		self.initializePiVariables()
		self.initializePandaVarialbes()


	def initializePiVariables(self):
		self.ail = 0
		self.ele = 0
		self.thr = 0
		self.rud = 0
		self.gyroX = 0
		self.gyroY = 0
		self.yaw = 0


	#initializing more global variables
	def initializePandaVarialbes(self):	
		self.cameraSpeed = 0.5
		self.moveSpeed = 0.2
		self.quadDistance = 15
		self.noYawInput = True
		self.throttlePower = "o "
		self.dX = 0
		self.dTheta = 0
		self.isMoving = False
		self.dictOfRecords = dict()
		self.keysPressedDown = set()
		self.username = ""
		self.initializePandaVariablesPart2()

	def initializePandaVariablesPart2(self):
		self.timer = 0.00
		self.timerRunning = False
		self.timerLastModified = self.getTime()
		self.initializePromptTextPart1()
		self.initializePromptTextPart2()
		self.initializePressedDownKeyText()	
		self.toggleLiftOff = True
		self.listOfModelPaths= ['models/fighter/fighter', 
		'models/boeing/boeing707', 'models/r2d2/r2d2', 
		'models/blimp/blimp', 'models/seeker/seeker', 
		'models/jeep/jeep']
		self.modelIndex = 0		

	def initializePromptTextPart1(self):
		self.timerText = TextNode('timer')
		self.timerText.setText("Time:" + "0" + str(self.timer))
		self.timerText.setShadow(0.05, 0.05)
		self.timerTextNodePath = aspect2d.attachNewNode(self.timerText)
		self.timerTextNodePath.setScale(0.07)
		self.timerTextNodePath.setPos(1.2,0,0.9)

		self.saveTimeText = TextNode('would you like to save?')
		self.saveTimeText.setText('')#
		self.saveTimeText.setShadow(0.05, 0.05)
		self.saveTimeTextNodePath = aspect2d.attachNewNode(self.saveTimeText)
		self.saveTimeTextNodePath.setScale(0.07)
		self.saveTimeTextNodePath.setPos(1.1, 0, 0.8)


	def initializePromptTextPart2(self):
		self.thrStatus = ""
		self.loadModelsText = "Select your model!\nPress [B] to go back!"
		line1 = "Press [H] for Help!\n"
		line2 = "Press [L] to load high scores!\n"
		line3 = "Press [G] to change skins!\n\n"
		line4 = "Throttle Status: " + self.thrStatus
		self.helperText = line1 + line2 + line3 + line4

		self.helpText = TextNode('help')
		self.helpText.setText(self.helperText)
		self.helpTextNodePath = aspect2d.attachNewNode(self.helpText)
		self.helpTextNodePath.setScale(0.07)
		self.helpTextNodePath.setPos(-1.5,0,0.9)
		self.helpText.setShadow(0.05, 0.05)
		self.initializeUserInputText()

	def initializeUserInputText(self):
		self.loadModelText = TextNode('load models')
		self.loadModelText.setText("")
		self.loadModelTextNodePath = aspect2d.attachNewNode(self.loadModelText)
		self.loadModelTextNodePath.setScale(0.07)
		self.loadModelTextNodePath.setPos(-1.5,0,0.9)
		self.loadModelText.setShadow(0.05, 0.05)

		self.defaultText = "type in your name!"
		self.textObject=OnscreenText(text=self.defaultText,pos = (1.25,-0.95), 
		scale = 0.07,fg=(1,0.5,0.5,1),align=TextNode.ACenter,mayChange=1)
		self.nameEntry=DirectEntry(text = "",scale=.05,command=self.setText,
		initialText="Type Something", numLines = 2,focus=1,
		focusInCommand=self.clearText)
		self.nameEntry.setPos(1.05,0,-0.8)

	def initializePressedDownKeyText(self):
		self.initializePressedDownKeysPart1()
		self.initializePressedDownKeysPart2()
		self.initializePressedDownKeysPart3()
		self.initializePressedDownKeysPart4()

	def initializePressedDownKeysPart1(self):
		self.wText = TextNode('w')
		self.wText.setText("w")
		self.wText.setShadow(0.05, 0.05)
		self.wTextNodePath = aspect2d.attachNewNode(self.wText)
		self.wTextNodePath.setScale(0.07)
		self.wTextNodePath.setPos(-1.6,0,-0.75)

		self.sText = TextNode('s')
		self.sText.setText("s")
		self.sText.setShadow(0.05, 0.05)
		self.sTextNodePath = aspect2d.attachNewNode(self.sText)
		self.sTextNodePath.setScale(0.07)
		self.sTextNodePath.setPos(-1.35,0,-0.75)

	def initializePressedDownKeysPart2(self):
		self.aText = TextNode('a')
		self.aText.setText("a")
		self.aText.setShadow(0.05, 0.05)
		self.aTextNodePath = aspect2d.attachNewNode(self.aText)
		self.aTextNodePath.setScale(0.07)
		self.aTextNodePath.setPos(-1.1,0,-0.75)	

		self.dText = TextNode('d')
		self.dText.setText("d")
		self.dText.setShadow(0.05, 0.05)
		self.dTextNodePath = aspect2d.attachNewNode(self.dText)
		self.dTextNodePath.setScale(0.07)
		self.dTextNodePath.setPos(-0.85,0,-0.75)

	def initializePressedDownKeysPart3(self):
		self.upText = TextNode('Up')
		self.upText.setText("Up")
		self.upText.setShadow(0.05, 0.05)
		self.upTextNodePath = aspect2d.attachNewNode(self.upText)
		self.upTextNodePath.setScale(0.07)
		self.upTextNodePath.setPos(-1.6,0,-0.85)

		self.downText = TextNode('Down')
		self.downText.setText("Down")
		self.downText.setShadow(0.05, 0.05)
		self.downTextNodePath = aspect2d.attachNewNode(self.downText)
		self.downTextNodePath.setScale(0.07)
		self.downTextNodePath.setPos(-1.35,0,-0.85)

	def initializePressedDownKeysPart4(self):
		self.rightText = TextNode('Left')
		self.rightText.setText("Left")
		self.rightText.setShadow(0.05, 0.05)
		self.rightTextNodePath = aspect2d.attachNewNode(self.rightText)
		self.rightTextNodePath.setScale(0.07)
		self.rightTextNodePath.setPos(-1.1,0,-0.85)	

		self.leftText = TextNode('Right')
		self.leftText.setText("Right")
		self.leftText.setShadow(0.05, 0.05)
		self.leftTextNodePath = aspect2d.attachNewNode(self.leftText)
		self.leftTextNodePath.setScale(0.07)
		self.leftTextNodePath.setPos(-0.85,0,-0.85)		

	def setText(self, textEntered):
		self.textObject.setText(textEntered)
		self.username = self.textObject.getText()

		#clear the text
	def clearText(self):
		self.nameEntry.enterText('')


	#returns the date for the timer method
	def getTime(self):
		time = str(datetime.datetime.now())
		return (time[11:]) 

	#this returns the string date in a format that is compatibile for
	#the save and load files method

	def getDateTime(self):
		time = str(datetime.datetime.now())
		return time[:10] + "," + time[11:19]

	#loads the environments. So far I have the sky model and a jungle 
	#environment.

	def loadEnvironments(self):
		self.disableMouse()

		self.environ = self.loader.loadModel("models/sky/blue-sky-sphere")
		self.environ.reparentTo(self.render)
		self.environ.setScale(0.25, 0.25, 0.25)
		self.environ.setPos(0, 0, 0)

		self.environ1 = self.loader.loadModel("models/course/course1")
		self.environ1.reparentTo(self.render)
		self.environ1.setScale(2.0, 2.0, 2.0)
		self.environ1.setPos(0, 0, 0)
		self.environ1.setHpr(123,0,0)


	#this method will load all of the models. So far I only have two, but
	#I intend on adding more later

	def loadModels(self):
		self.loadPanda()
		self.loadQuad()

	#this method loads the panda model. It has a walk animation, as well
	#as a movement path. I modified parts of this code while following a panda3D tutorial:
	#https://www.panda3d.org/manual/index.php/Loading_and_Animating_the_Panda_Model

	def loadPanda(self):
		self.pandaActor = Actor("models/panda-model", 
			{"walk": "models/panda-walk4"})
		self.pandaActor.setScale(0.005, 0.005, 0.005)
		self.pandaActor.reparentTo(self.render)
		self.pandaActor.setHpr(90,0,0)
		# Loop its animation.
		self.pandaActor.loop("walk")
		# Create the four lerp intervals needed for the panda to move
		pandaPosInterval1 = self.pandaActor.posInterval(13, Point3(-33, 0, -1),
													startPos=Point3(-41, 0,-1))
		pandaPosInterval2 = self.pandaActor.posInterval(13, Point3(-41, 0, -1),
													startPos=Point3(-33, 0, -1))
		pandaHprInterval1 = self.pandaActor.hprInterval(3, Point3(-90, 0, 0),
													startHpr=Point3(90, 0, 0))
		pandaHprInterval2 = self.pandaActor.hprInterval(3, Point3(90, 0, 0),
													startHpr=Point3(-90, 0, 0))
		# Create and play the sequence that coordinates the intervals.
		self.pandaPace = Sequence(pandaPosInterval1,pandaHprInterval1, 
			pandaPosInterval2, pandaHprInterval2, name="pandaPace")
		self.pandaPace.loop()

	#this will load the quad model. As of right now, it is only a demo model
	#but I plan on making my own quad model later

	def loadQuad(self):
		# Load and transform the panda actor.
		self.quad = loader.loadModel('models/fighter/fighter')
		self.quad.reparentTo(self.render)
		self.quad.setScale(0.15, 0.15, 0.15)
		self.quad.setPos(self.camera, 0, self.quadDistance,-2)
		self.quad.setHpr(self.camera, 0,0,0)

	#sets the keyinputs. I split it into two methods to make it more 
	#readable
	#the way the key inputs are read in panda is pressing the key down
	#generates one pulse, and then releasing the button generates another
	#pulse. Each time a pulse is fired, panda will set the value of a key
	#to be either True (when it's pressed down) or False (when it's not 
	#pressed down). 

	def initializeKeys1(self):
		self.accept("escape", sys.exit)

		self.accept("arrow_up", self.setKey, ["u", 1, server])
		self.accept("arrow_up-up", self.setKey, ["u", 0, server])

		self.accept("arrow_down", self.setKey, ["e", 1, server])
		self.accept("arrow_down-up", self.setKey, ["e", 0, server])

		self.accept("arrow_right", self.setKey, ["l", 1, server])
		self.accept("arrow_right-up", self.setKey, ["l", 0, server])

		self.accept("arrow_left", self.setKey, ["r", 1, server])
		self.accept("arrow_left-up", self.setKey, ["r", 0, server])


		self.accept('g', self.pickModel, [])
	#part two of initialize keys

	def initializeKeys2(self):
		self.accept("w", self.setKey, ["w", 1, server])
		self.accept("w-up", self.setKey, ["w", 0, server])
		self.accept("s", self.setKey, ["s", 1, server])
		self.accept("s-up", self.setKey, ["s", 0, server])
		self.accept("d", self.setKey, ["d", 1, server])
		self.accept("d-up", self.setKey, ["d", 0, server])
		self.accept("a", self.setKey, ["a", 1, server])
		self.accept("a-up", self.setKey, ["a", 0, server])
		self.accept('8', self.sendMsg, ['8', server]) #arm
		self.accept('9', self.sendMsg, ['9', server]) #disarm
		self.accept('l', self.displayHighScores, [])
		self.accept('p', self.startStopTimer, [])
		self.accept('h', self.getHelp, [])
		self.accept('b', self.returnToGame, [])
		self.accept('y', self.saveTime, [])
		self.accept('n', self.resetTime, [])

		self.accept('1', self.swapModel, [1])
		self.accept('2', self.swapModel, [2])
		self.accept('3', self.swapModel, [3])
		self.accept('4', self.swapModel, [4])
		self.accept('5', self.swapModel, [5])
		self.accept('6', self.swapModel, [6])

	#saves the times on a text file

	def swapModel(self, index):
		# self.modelIndex += 1
		# self.modelIndex = self.modelIndex % len(self.listOfModelPaths)
		index -= 1
		if index < len(self.listOfModelPaths):
			path = self.listOfModelPaths[index]
			self.quad.removeNode()
			self.quad = loader.loadModel(path)
			self.quad.reparentTo(self.render)
			scale = self.pickScale(path)
			self.quad.setScale(scale)
			self.quad.setPos(self.camera, 0, self.quadDistance,-2)
			self.quad.setHpr(self.camera, 0,0,0)

	#this is the overall method used to display the models when the [G]
	#button is pressed. I split it into a top down design so it is easier
	#to read

	def pickModel(self):
		self.loadPickModelPart1()
		self.loadPickModelPart2()
		self.loadPickModelPart3()
		self.loadPickModelTextPart1()
		self.loadPickModelTextPart2()
		self.loadPickModelTextPart3()

	#loads the Fighter and Boeing model

	def loadPickModelPart1(self):
		self.helpText.setText("")
		self.loadModelText.setText(self.loadModelsText)
		
		self.skin1 = self.loader.loadModel("models/fighter/fighter")
		self.skin1.reparentTo(self.render)
		self.skin1.setScale(0.1, 0.1, 0.1)
		self.skin1.setPos(self.camera, -4.5, self.quadDistance,2)
		self.skin1.setHpr(self.camera, 180, 0,0)

		self.skin2 = self.loader.loadModel("models/boeing/boeing707")
		self.skin2.reparentTo(self.render)
		self.skin2.setScale(0.08, 0.08, 0.08)
		self.skin2.setPos(self.camera, 0.5, self.quadDistance,2)
		self.skin2.setHpr(self.camera, 180, 0,0)

	#loads the R2D2 and blimp model

	def loadPickModelPart2(self):
		self.skin3 = self.loader.loadModel("models/r2d2/r2d2")
		self.skin3.reparentTo(self.render)
		self.skin3.setScale(0.5, 0.5, 0.5)
		self.skin3.setPos(self.camera, 4.5, self.quadDistance,2)
		self.skin3.setHpr(self.camera, 180, 0,0)

		self.skin4 = self.loader.loadModel("models/blimp/blimp")
		self.skin4.reparentTo(self.render)
		self.skin4.setScale(0.03, 0.03, 0.03)
		self.skin4.setPos(self.camera, -4.5, self.quadDistance,-0.5)
		self.skin4.setHpr(self.camera, 180, 0,0)

	#loads the seeker and jeep model

	def loadPickModelPart3(self):
		self.skin5 = self.loader.loadModel("models/seeker/seeker")
		self.skin5.reparentTo(self.render)
		self.skin5.setScale(0.8, 0.8, 0.8)
		self.skin5.setPos(self.camera, 0.5, self.quadDistance,-0.5)
		self.skin5.setHpr(self.camera, 180, 0,0)

		self.skin6 = self.loader.loadModel("models/jeep/jeep")
		self.skin6.reparentTo(self.render)
		self.skin6.setScale(0.17, 0.17, 0.17)
		self.skin6.setPos(self.camera, 4.5, self.quadDistance,-1.0)
		self.skin6.setHpr(self.camera, 0, 0,0)

	#loads label text for the figher and boeing

	def loadPickModelTextPart1(self):
		self.skin1Text = TextNode('skin1')
		self.skin1Text.setText("[1] - Fighter")
		self.skin1Text.setShadow(0.05, 0.05)
		self.skin1TextNodePath = aspect2d.attachNewNode(self.skin1Text)
		self.skin1TextNodePath.setScale(0.07)
		self.skin1TextNodePath.setPos(-1.3,0,0.3)	

		self.skin2Text = TextNode('skin2')
		self.skin2Text.setText("[2] - Boeing707")
		self.skin2Text.setShadow(0.05, 0.05)
		self.skin2TextNodePath = aspect2d.attachNewNode(self.skin2Text)
		self.skin2TextNodePath.setScale(0.07)
		self.skin2TextNodePath.setPos(-0.1,0,0.3)	

	#loads label text for R2D2 and the Blimp

	def loadPickModelTextPart2(self):

		self.skin3Text = TextNode('skin3')
		self.skin3Text.setText("[3] - R2D2")
		self.skin3Text.setShadow(0.05, 0.05)
		self.skin3TextNodePath = aspect2d.attachNewNode(self.skin3Text)
		self.skin3TextNodePath.setScale(0.07)
		self.skin3TextNodePath.setPos(1,0,0.3)	

		self.skin4Text = TextNode('skin4')
		self.skin4Text.setText("[4] - Blimp")
		self.skin4Text.setShadow(0.05, 0.05)
		self.skin4TextNodePath = aspect2d.attachNewNode(self.skin4Text)
		self.skin4TextNodePath.setScale(0.07)
		self.skin4TextNodePath.setPos(-1.3,0,-0.5)	

	#loads the label text for Seeker and Jeep

	def loadPickModelTextPart3(self):
		self.skin5Text = TextNode('skin5')
		self.skin5Text.setText("[5] - Seeker")
		self.skin5Text.setShadow(0.05, 0.05)
		self.skin5TextNodePath = aspect2d.attachNewNode(self.skin5Text)
		self.skin5TextNodePath.setScale(0.07)
		self.skin5TextNodePath.setPos(-0.1,0,-0.5)	

		self.skin6Text = TextNode('skin6')
		self.skin6Text.setText("[6] - Jeep")
		self.skin6Text.setShadow(0.05, 0.05)
		self.skin6TextNodePath = aspect2d.attachNewNode(self.skin6Text)
		self.skin6TextNodePath.setScale(0.07)
		self.skin6TextNodePath.setPos(1,0,-0.5)	

	#this is the overall method that will return how the model should
	#be sized. All of this is magic numbers, and I found them based on 
	#my personal preference to how the models should look aesthetically 

	def pickScale(self, path):
		if path == "models/fighter/fighter":
			return (0.15,0.15,0.15)
		elif path == "models/boeing/boeing707":
			return (0.1,0.1,0.1)
		elif path == "models/r2d2/r2d2":
			return (0.7,0.7,0.7)
		elif path == "models/blimp/blimp":
			return (0.05,0.05,0.05)
		elif path == "models/seeker/seeker":
			return (0.8,0.8,0.8)
		elif path == 'models/jeep/jeep':
			return (0.25,0.25,0.25)

	#This will save whatever time the user has, assuming the inputted
	#username isn't empty. It will save the data into a text file called
	#"Records"

	def saveTime(self):
		savedTime = self.timer
		if self.username != '':
			if (os.path.isfile('Records')):
				file = open('Records', "r")
				result = (self.username + "," + self.getDateTime() + "," 
					+ savedTime + "\n")
				stringOfRecords = file.read()
				stringOfRecords += result
				file = open('Records', "w")
				file.write(stringOfRecords)
			else:
				file = open('Records', "w")
				file.write(self.username + "," + self.getDateTime() + "," 
					+ savedTime + "\n")
		self.timerText.setText("Time: 00.0")
		self.timer = 0

	#this will reset the timerText to 0:00 and the 
	#timer variable back to zero.

	def resetTime(self):
		self.timerText.setText("Time: 00.0")
		self.timer = 0

	#this will reset the menu screen to the default display. I had to add
	#a try block to it just in case some of the models don't properly load
	#if they don't load, and you try to delete them, the program will crash

	def returnToGame(self):
		try:
			self.helpText.setText(self.helperText)
			self.loadModelText.setText("")
			self.skin1.removeNode()
			self.skin2.removeNode()
			self.skin3.removeNode()
			self.skin4.removeNode()
			self.skin5.removeNode()
			self.skin6.removeNode()
			self.skin1Text.setText("")
			self.skin2Text.setText("")
			self.skin3Text.setText("")
			self.skin4Text.setText("")
			self.skin5Text.setText("")
			self.skin6Text.setText("")
		except: pass

	#This is the help menu when [H] is pressed

	def getHelp(self):
		line1 = "Press [B] to go back\n"
		line2 = "[W] - Move forwards\n"
		line3 = "[S] - Move backwards\n"
		line4 = "[D] - Move right\n"
		line5 = "[A] - Move left\n"
		line6 = "[Right Arrow] - Rotate right\n"
		line7 = "[Left Arrow] - Rotate left\n"
		line8 = "[Up Arrow] - Move up\n"
		line9 = "[Down Arrow] - Move down\n"
		line10 = "[8] - Arm Copter\n"
		line11 = "[9] - Disarm Copter"
		self.helpText.setText(line1 + line2 + line3 + line4 + line5 + line6 
			+ line7 + line8 + line9 + line10 + line11)

	#opens up a file called "records" if it exists, and then proceeds to load
	#and read the data

	def displayHighScores(self):
		if (os.path.isfile('Records')):
			file = open('Records', 'r')
			stringRecords = file.read()
			stringRecords = stringRecords.split('\n')[:-1]
			self.dictOfRecords = dict()
			for person in stringRecords:
				person = person.split(',')
				key = person[0] #sets the key index to the person's name
				person = person[1:] #cuts the name part off now
				if key in self.dictOfRecords:
					self.dictOfRecords[key] += [person]
				else:
					self.dictOfRecords[key] = [person]
			self.organizeDictionaryOfRecords()

	#once the file has been read, this method will decipher the dictionary of
	#people with their lists of times. It will then sort them in descending order
	#this is all destructive, by the way.

	def organizeDictionaryOfRecords(self):
		for person in self.dictOfRecords: #jason, Jason
			if len(self.dictOfRecords[person]) > 1:
				self.sortTimes(self.dictOfRecords[person])
		line1 = "Record Board: (date, datetime, time)\n"
		line2 = "Press [B] to go back\n"
		sortedStringOfRecords = line1 + line2
		for person in self.dictOfRecords:
			sortedStringOfRecords += person + ":\n"
			for stats in self.dictOfRecords[person]:
				for stat in stats:
					sortedStringOfRecords += stat + "\t\t"
				sortedStringOfRecords += "\n"
			sortedStringOfRecords += "\n"
		self.helpText.setText(sortedStringOfRecords)


	#this is a variation of the merge method in merge sort, modified to sort
	#lists of lists.

	def merge(self, l, s1, s2, end):
		index1 = s1
		index2 = s2
		length = end - s1
		aux = [None] * length
		for i in range(length):
			if (index1 == s2) or ((index2 != end) and 
	(self.convertToSeconds(l[index1][2])>self.convertToSeconds(l[index2][2]))):
				aux[i] = l[index2]
				index2 += 1
			else:
				aux[i] = l[index1]
				index1 += 1
		for i in range(s1, end):
			l[i] = aux[i - s1]

	#when I was comparing times, I forgot I also had to compare times when it
	#read like 1:02, and I was no longer just comparing seconds. So I had to 
	#write a method that will conver the time first to seconds before it 
	#gets compared.

	def convertToSeconds(self, time):
		if ":" in time:
			minutes = float(time[:time.index(":")])
			seconds = minutes * 60 + float(time[time.index(":") + 1:])
			return seconds
		return float(time)

	#this is parent the "mergeSort", modified to sort the list of lists

	def sortTimes(self, listOfTimes):
		n = len(listOfTimes)
		step = 1
		while (step < n):
			for s1 in range(0, n, 2 * step):
				s2 = min(s1 + step, n)
				end = min(s1 + 2 * step, n)
				self.merge(listOfTimes, s1, s2, end)
			step *= 2

	#toggles the self.timerRunning variable, and sets the timerBegin variable
	#if the timer just started

	def startStopTimer(self):
		if not self.timerRunning:
			self.timerBegin = self.getTime()
		self.timerRunning = not self.timerRunning

	#to make things more organized, I combined all of the threaded methods
	#here, so I can modify/add more in the future if needed

	def startThreads(self):
		thread.start_new_thread(self.rotateQuad, (server,))
		thread.start_new_thread(self.handleServerMsg, (server,))
		thread.start_new_thread(self.moveCamera, (server,))	
		thread.start_new_thread(self.spinQuad, (server, ))
		thread.start_new_thread(self.evaluateHits, (server, ))	
		thread.start_new_thread(self.runTimer, (server, ))

	#this method is only used for button actions that don't require buttons
	#to be held down. For example, pressing 8 and 9 will arm and disarm the
	#copter, and holding them down won't do anything. So sendMsg will basically
	#send a single pulse to the server, which will know what to do for 
	#specific single pulses.

	def sendMsg(self, msg, server):
		server.send(bytes(msg))

	#evalKey is only used by the down button. It essentially determines
	#if the copter is on the ground before it tries to lower the quad's
	#actual throttle. I do this to simulate more of a "real" effect, where
	#the quad in real life will only shut down once the quad in the
	#simulation has actually touched the ground.

	def evalKey(self, key, val, server):
		if self.quad.getZ() < 0 and not self.keys['e']:
			self.setKey(key, val, server)
		else:
			self.keys[key] = val

	#set key will merely change the dictionary of keys to whatever value
	#it is inputed. Then, it will send a pulse to the server, which will
	#read it as a double pulse and modify its own variables accordingly. 

	def setKey(self, key, val, server):
		self.keys[key] = val
		server.send(bytes(key))

		for key in self.keys:
			if self.keys[key]:
				self.keysPressedDown.add(key)
			else:
				if key in self.keysPressedDown:
					self.keysPressedDown.remove(key)

		# self.updatePressedDownKeys()
		self.setPressedDownKeys()

	def setPressedDownKeys(self):
		if self.keys['w']: self.wText.setText('w')
		else: self.wText.setText('')
		if self.keys['a']: self.aText.setText('a')
		else: self.aText.setText('')
		if self.keys['s']: self.sText.setText('s')
		else: self.sText.setText('')
		if self.keys['d']: self.dText.setText('d')
		else: self.dText.setText('')
		if self.keys['u']: self.upText.setText('Up')
		else: self.upText.setText('')
		if self.keys['e']: self.downText.setText('Down')
		else: self.downText.setText('')
		if self.keys['l']: self.leftText.setText('Right')
		else: self.leftText.setText('')
		if self.keys['r']: self.rightText.setText('Left')
		else: self.rightText.setText('')


	# def updatePressedDownKeys(self): pass


	def moveCamera(self, server):
		while True:
			try:
				if self.quad.getZ() < 0:
					server.send(bytes('1')) #ground
				else:
					server.send(bytes('0')) #air
				if self.quad.getZ() > 0:	
					if self.keys["w"]:
						self.camera.setPos(self.camera, 0, self.moveSpeed, 0)
						self.quad.setPos(self.camera, 0, self.quadDistance, -2)
						self.tiltForward()
	
					elif self.keys["s"]:
						self.camera.setPos(self.camera, 0, -self.moveSpeed, 0)
						self.quad.setPos(self.camera, 0, self.quadDistance, -2)
						self.tiltBackward()
					else:
						self.pitchSelfLevel()
	
					if self.keys["d"]:
						self.quad.setHpr(self.quad, 0, 0, pi / 8)
						self.isMoving = True
	
					elif self.keys["a"]:
						self.quad.setHpr(self.quad, 0, 0, -pi / 8)
						self.isMoving = True				
	
					elif not (self.keys['d'] and self.keys['a']):
						self.isMoving = False
						self.driftStabilize()
					
				self.moveCameraPart2(server)
			except: pass

	def moveCameraPart2(self, server):
		if self.keys["u"]:
			if self.thr >= 6.4:
				if self.toggleLiftOff:
					self.thrStatus = "Take off!"
					line1 = "Press [H] for Help!\n"
					line2 = "Press [L] to load high scores!\n"
					line3 = "Press [G] to change skins!\n\n"
					line4 = "Throttle Status: " + self.thrStatus
					self.helpText.setText(line1 + line2 + line3 + line4)
					self.toggleLiftOff = False

				self.camera.setPos(self.camera, 0, 0, self.moveSpeed / 2)
				self.quad.setPos(self.camera, 0, self.quadDistance, -2)
			else:
				self.thrStatus = "Starting up motors..."
				line1 = "Press [H] for Help!\n"
				line2 = "Press [L] to load high scores!\n"
				line3 = "Press [G] to change skins!\n\n"
				line4 = "Throttle Status: " + self.thrStatus
				self.helpText.setText(line1 + line2 + line3 + line4)

		self.moveCameraPart3(server)


		#this is the down arrow, but I had no other key to set it to : /
		#the keys sent must be of one character long because thats how
		#the server can read messages (it goes through each message
		#character by character)
		
	def moveCameraPart3(self, server):
		if self.keys["e"]: 
			if self.quad.getZ() > -0.01:
				self.camera.setPos(self.camera, 0, 0, -self.moveSpeed / 2)
				self.quad.setPos(self.camera, 0, self.quadDistance, -2)
			elif self.thr < 5.3:
				self.thrStatus = "Landed!"
				line1 = "Press [H] for Help!\n"
				line2 = "Press [L] to load high scores!\n"
				line3 = "Press [G] to change skins!\n\n"
				line4 = "Throttle Status: " + self.thrStatus
				self.helpText.setText(line1 + line2 + line3 + line4)

			else:
				self.toggleLiftOff = True
				self.thrStatus = "Landing..."
				line1 = "Press [H] for Help!\n"
				line2 = "Press [L] to load high scores!\n"
				line3 = "Press [G] to change skins!\n\n"
				line4 = "Throttle Status: " + self.thrStatus
				self.helpText.setText(line1 + line2 + line3 + line4)
		self.moveCameraPart4(server)

	def moveCameraPart4(self, server):
		if self.keys["r"]:
			self.noYawInput = False
		elif self.keys['l']:
			self.noYawInput = False
		elif not (self.keys["r"] and self.keys["l"]):
			self.yawSelfLevel()

		time.sleep(0.01)


		#this method if replacing the if statement above will manually control
		#the rotation of the quad regardless of the overall orientation of
		#the physical quad. I'm going to leave the code here just in case
		#I ever need to manually control the quad in the future.

		# if self.keys["l"]:
		# 	self.camera.setHpr(self.camera, -self.cameraSpeed / 2, 0,0)
		# 	deltaX = - (cos(radians(90 - self.cameraSpeed)) * 
		# 		self.quadDistance) * cos(radians(self.cameraSpeed))
		# 	deltaY = (cos(radians(90 - self.cameraSpeed)) * 
		# 		self.quadDistance) * sin(radians(self.cameraSpeed))
		# 	self.camera.setPos(self.camera, deltaX, deltaY, 0)
		# 	self.quad.setHpr(self.camera, 0,self.quad.getP(),self.quad.getR())

		# elif self.keys["r"]:
		# 	self.camera.setHpr(self.camera, self.cameraSpeed / 2, 0, 0)
		# 	deltaX = (cos(radians(90 - self.cameraSpeed)) * 
		# 		self.quadDistance) * cos(radians(self.cameraSpeed))
		# 	deltaY = (cos(radians(90 - self.cameraSpeed)) * 
		# 		self.quadDistance) * sin(radians(self.cameraSpeed))
		# 	self.camera.setPos(self.camera, deltaX, deltaY, 0)
		# 	self.quad.setHpr(self.camera,0,self.quad.getP(),self.quad.getR())



	def tiltForward(self):
		desiredVal = -15
		error = desiredVal - self.quad.getP()
		self.quad.setHpr(self.quad, 0, error * 0.05, 0)

	def tiltBackward(self):
		desiredVal = 15
		error = desiredVal - self.quad.getP()
		self.quad.setHpr(self.quad, 0, error * 0.05, 0)

	def pitchSelfLevel(self):
		desiredVal = 0
		error = desiredVal - self.quad.getP()
		self.quad.setHpr(self.quad, 0, error * 0.05, 0)

	#currently working on this aspect of the simulation: the quad is noted
	#to have random bursts of movement which causes a lot of jitter; trying
	#to see how I can manage to stabilize the motion

	def rotateQuad(self, server): #this rotates roll
		while True:
			try:
				self.updateSaveTimer()
				#this will rotate the quad
				error = self.gyroX / 2 - self.quad.getR()
				self.quad.setHpr(self.quad, 0, 0, error * 0.01)
				if self.isMoving:
					maxVelocity = 0.2
					sign = 1
					if self.quad.getR() < 0:
						sign = -1
					error = (sign * maxVelocity) - self.dX
					self.dX += error * 0.01
					self.camera.setPos(self.camera, self.dX, 0, 0)
					self.quad.setPos(self.camera, 0,self.quadDistance,-2)
			except: pass
			time.sleep(0.01)

	#This is prompted whenever the quad crosses the finish line. 

	def updateSaveTimer(self):
		if not self.timerRunning and self.timer != 0:
			text = 'Would you like to\nsave this time?\n(Y/N)'
			self.saveTimeText.setText(text)
		else:
			self.saveTimeText.setText('')

	#This is another stability algorithm tha tI wrote. Eseentially, it will
	#bring the copter to a smooth stop instead of it being jittery. However,
	#this can only work so well, as the quad is still 90% affected by the
	#physical orientation.

	def driftStabilize(self): 
		error = 0 - self.dX
		self.dX += error * 0.05
		self.camera.setPos(self.camera, self.dX, 0, 0)
		self.quad.setPos(self.camera, 0,self.quadDistance,-2)

	#controls the yaw direction of the quad. 

	def spinQuad(self, server):
		while True:
			try:
				if not self.noYawInput:
					sign = 1
					if self.yaw < 0:
						sign = -1
					self.dTheta = ((self.yaw / 100)) * self.cameraSpeed * 4
					self.camera.setHpr(self.camera, self.dTheta, 0,0)
					absRotationSpeed = abs(self.dTheta)
					deltaX = sign * (cos(radians(90 - absRotationSpeed)) * 
						self.quadDistance) * cos(radians(absRotationSpeed))
					deltaY = (cos(radians(90 - absRotationSpeed)) * 
						self.quadDistance) * sin(radians(absRotationSpeed))
					self.camera.setPos(self.camera, deltaX, deltaY, 0)
					self.quad.setPos(self.camera, 0,self.quadDistance, -2)
					self.quad.setHpr(self.camera, 0,self.quad.getP(),
						self.quad.getR())
			except: pass			
			time.sleep(0.01)

	#yaw refers to the rotation about its z axis. This will smoothen out
	#the quad's z axis rotation

	def yawSelfLevel(self):
		self.noYawInput = True
		error = 0 - self.dTheta
		self.dTheta += error * 0.05
		self.camera.setHpr(self.camera, self.dTheta, 0, 0)
		self.quad.setHpr(self.camera, 0, self.quad.getP(), self.quad.getR())
		self.quad.setPos(self.camera, 0, self.quadDistance, -2)

	#generic evaluateHits function. Will add more onto it later.

	def evaluateHits(self, server):
		while True:
			try:
				x = self.quad.getX()
				y = self.quad.getY()
				if (x > 18 and x < 38) and (y > 9 and y < 14):
					self.handleTimer()
				# self.helpText.setText(str(self.thr))
			except: pass
			time.sleep(0.1)

	#an issue that I ran into was having the timer run on and off when
	#the quad is hovering over the finish line, since it takes time
	#to actually physically cross the finish line. Therefore, I made a function
	#that makes sure the time between each time the quad hits the finish
	#line is greater than 1 second.

	def handleTimer(self):
		timeElapsed = self.calculateTime(self.getTime(), 
			self.timerLastModified)
		self.timerLastModified = self.getTime()
		if int(timeElapsed[0]) >= 1 or int(timeElapsed[1]) >= 1:
			self.startStopTimer()

	#this time method is run continuously. However, it will only actually do 
	#something if the self.timerRunning variable is true. It will update
	#the self.timerText text to the running time

	def runTimer(self, server):
		while True:
			if self.timerRunning:
				self.timer = self.calculateTime(self.getTime(),self.timerBegin)
				self.timerText.setText("Time: " + self.timer)
			time.sleep(0.1)

	#calculates the time elapsed given a current time and the start time.
	#return a string in the format MM:SS, unless one of those values = 0,
	#then it will ignore that part.

	def calculateTime(self, currentTime, startTime):
		(currentTime, startTime)=(currentTime.split(':'),startTime.split(':'))
		resultTimer = []
		for timerIndex in range(len(startTime)):
			diff=float(currentTime[timerIndex])-float(startTime[timerIndex])
			if diff < 0:
				diff += 60
				resultTimer[timerIndex -1 ] -= 1
			resultTimer.append(diff)
		time = ""
		(minutes,seconds)=(resultTimer[1],resultTimer[2])
		if minutes != 0:
			time += str(minutes)[0] + ":"
		if seconds != 0:
			seconds = str(seconds)[:4] + ":"
			if seconds.index('.') == 1: seconds = "0" + seconds
			time += seconds
		return time[:-1]

	#this is a thread that is constantly run to update the server variables
	#I ended up not using a bunch of these variables, because I ran into 
	#a lot of lag whenever I tried to constantly update textFields to read
	#whatever the server sends.

	def handleServerMsg(self, server):
		while True:
			msg = server.recv(1000).decode('UTF-8')
			try:
				msg = eval(msg)
				self.distance = msg["distance"]
				self.gyroX = msg["gyroX"]
				self.gyroY = msg["gyroY"]
				self.yaw = msg["yaw"] // 100
				self.ele = msg["ele"]
				self.rud = msg["rud"]
				self.thr = msg["thr"]
				# print(self.thr)
				self.ail = msg["ail"]
				# print(self.thr)
			except:
				pass
Beispiel #32
0
class DPiece(DistributedSmoothNode):
    def __init__(self, cr):
        self.modelName = ""
        DistributedSmoothNode.__init__(self, cr)

        self.setCacheable(1)
        self.model = None
        self.tagText = None
        self.nameTag = None

        self.acceptOnce("BoardAnimationDone", self.show)

    def generate(self):
        DistributedSmoothNode.generate(self)
        self.activateSmoothing(True, False)
        self.startSmooth()

    def announceGenerate(self):
        DistributedSmoothNode.announceGenerate(self)
        self.reparentTo(render)
        self.d_getNameForNameTag()

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

    def delete(self):
        if self.model is not None:
            self.model.removeNode()
        if self.nameTag is not None:
            self.nameTag.removeNode()
        DistributedSmoothNode.delete(self)

    def show(self):
        """Shows the piece and name tag of the player if they are already
        created. Otherwise it will spawn a task to check until it can finally be
        shown correctly."""
        if self.model is not None:
            if self.model.isHidden():
                self.model.show()
                self.model.setTransparency(1)
                LerpColorInterval(self.model, 1, self.model.getColor(),
                                  (0, 0, 0, 0)).start()
        else:
            taskMgr.doMethodLater(0.5,
                                  self.show,
                                  "retryShowPiece",
                                  extraArgs=[])

        if self.nameTag is not None:
            if self.nameTag.isHidden():
                self.nameTag.show()
                self.nameTag.setTransparency(1)
                LerpColorInterval(self.nameTag, 1, self.nameTag.getColor(),
                                  (0, 0, 0, 0)).start()
        else:
            taskMgr.doMethodLater(0.5,
                                  self.show,
                                  "retryShowPiece",
                                  extraArgs=[])

    def setModel(self, modelName):
        """Set and load the given model and ask if the board animation has been
        finished yet to show the model."""
        if modelName == "": return
        self.modelName = modelName
        self.model = base.loader.loadModel(self.modelName)
        self.model.reparentTo(self)
        self.model.hide()
        base.messenger.send("checkBoardAnimationDone")

    def d_getNameForNameTag(self):
        # this will call the createNameTag function through the server as the
        # server has stored the name
        self.sendUpdate("getNameForNameTag")

    def createNameTag(self, name):
        """Create the floating name above a player and set the name. If a name
        tag has already been created it will simply update the text to the new
        name."""
        if self.nameTag is None:
            self.tagText = TextNode("NameTag")
            self.tagText.setText(name)
            self.tagText.setTextColor(0, 0, 0, 1)
            self.tagText.setAlign(TextNode.ACenter)
            self.nameTag = self.attachNewNode(self.tagText)
            self.nameTag.setBillboardAxis()
            self.nameTag.setZ(0.025)
            self.nameTag.setScale(0.007)
            self.nameTag.setShaderAuto(True)
            self.nameTag.hide()
        else:
            self.tagText.setText(name)
 def __init__(self, name, parent, pos = (0.0, 0.0, -0.5), scale = 0.09, color = (1.0, 1.0, 0, 1), sfx = None):
     self.color = color
     self._displaySfx = sfx
     textNode = TextNode('messageLabel.' + name)
     textNode.setTextColor(self.color)
     textNode.setAlign(TextNode.ACenter)
     textNode.setFont(ToontownGlobals.getSignFont())
     textNode.setShadow(0.06, 0.06)
     textNode.setShadowColor(0.5, 0.5, 0.5, 1.0)
     self.pos = pos
     self.scale = scale
     self.messageLabel = parent.attachNewNode(textNode)
     self.messageLabel.setPos(self.pos)
     self.messageLabel.setScale(self.scale)
     self.messageLabel.stash()
     self.transitionInterval = Sequence(name='%s.transitionInterval' % self.__class__.__name__)
Beispiel #34
0
    def __init__(self, base, Golog, folder_path, parent=None):
        # Set up basic attributes
        self.base = base
        self.golog = Golog
        self.bools = {'textboxes': True}
        self.buttons = dict()
        self.window_tasks = dict()
        self.bt = None
        self.mw = None
        self.listener = DirectObject()
        self.folder_path = folder_path
        self.file_path = os.path.abspath(self.folder_path + '/' +
                                         self.golog.label + '.golog')
        self.has_window = False
        self.parent = parent  #for autosaving up to original golog
        self.reset = self.basic_reset
        self.garbage = []  #list of deleted math_data/graphics_data etc.

        #create a 2d rende
        self.render2d = NodePath('2d render')
        self.camera2D = self.render2d.attachNewNode(Camera('2d Camera'))
        self.camera2D.setDepthTest(False)
        self.camera2D.setDepthWrite(False)
        lens = OrthographicLens()
        lens.setFilmSize(2, 2)
        lens.setNearFar(-1000, 1000)
        self.camera2D.node().setLens(lens)

        # make a dictionary of mode_heads in the underlying golog
        if hasattr(self.golog, 'mode_heads'):
            m = 0
            while m in self.golog.mode_heads.keys():
                m += 1  #get smallest unused mode_head index
            self.index = m
            self.label = self.golog.label + "_mode_head_" + str(self.index)
            self.golog.mode_heads[self.index] = self

        else:
            self.golog.mode_heads = dict()
            self.index = 0
            self.label = self.golog.label + "_mode_head_" + str(self.index)
            self.golog.mode_heads[self.index] = self
        ##########

        ### set up collision handling ###
        self.queue = CollisionHandlerQueue()
        self.selected = [[],
                         []]  #tracking previously selected nodes of each level

        # set up mouse picker
        self.pickerNode = CollisionNode('mouseRay')
        self.pickerNP = self.golog.camera.attachNewNode(
            self.pickerNode)  #attach collision node to camera
        self.pickerRay = CollisionRay()
        self.pickerNode.addSolid(self.pickerRay)
        self.pickerNode.set_into_collide_mask(
            0
        )  #so that collision rays don't collide into each other if there are two mode_heads
        self.golog.cTrav.addCollider(
            self.pickerNP, self.queue)  #send collisions to self.queue
        # set up plane for picking
        self.planeNode = self.golog.render.attachNewNode("plane")
        self.planeNode.setTag(
            "mode_head", self.label)  # tag to say it belongs to this mode_head
        self.planeNode.setTag("mode_node", 'plane')
        self.planeFromObject = self.planeNode.attachNewNode(
            CollisionNode("planeColNode"))
        self.planeFromObject.node().addSolid(
            CollisionPlane(Plane(Vec3(0, -1, 0), Point3(0, 0, 0))))
        ###
        # set up preview text
        self.textNP = self.render2d.attachNewNode(TextNode('text node'))
        self.textNP.setScale(.2)
        self.textNP.setPos(-1, 0, 0)
        self.textNP.show()
        #set up dragging info
        self.grabbed_dict = None
Beispiel #35
0
class ObjectLabel(VisibleObject):
    default_shown = False
    ignore_light = True
    font_init = False
    font = None
    appearance = None
    shader = None

    def __init__(self, names):
        VisibleObject.__init__(self, names)
        self.fade = 1.0

    @classmethod
    def create_shader(cls):
        cls.appearance = ModelAppearance()
        cls.appearance.has_attribute_color = True
        cls.appearance.has_material = False
        cls.appearance.texture = True
        cls.appearance.texture_index = 0
        cls.appearance.nb_textures = 1
        cls.appearance.transparency = True
        cls.appearance.transparency_blend = TransparencyBlend.TB_Alpha
        cls.appearance.alpha_mask = True
        cls.shader = BasicShader(lighting_model=FlatLightingModel())

    def check_settings(self):
        if self.parent.body_class is None:
            print("No class for", self.parent.get_name())
            return
        self.set_shown(bodyClasses.get_show_label(self.parent.body_class))

    @classmethod
    def load_font(cls):
        font = fontsManager.get_font(settings.label_font, Font.STYLE_NORMAL)
        if font is not None:
            cls.font = font.load()
        else:
            cls.font = None
        cls.font_init = True

    def create_instance(self):
        #print("Create label for", self.get_name())
        self.label = TextNode(self.parent.get_ascii_name() + '-label')
        if not self.font_init:
            self.load_font()
        if self.font is not None:
            self.label.set_font(self.font)
        name = bayer.decode_name(self.parent.get_label_text())
        self.label.setText(name)
        self.label.setTextColor(*srgb_to_linear(self.parent.get_label_color()))
        #node=label.generate()
        #self.instance = self.context.annotation.attachNewNode(node)
        #self.instance.setBillboardPointEye()
        #node.setIntoCollideMask(GeomNode.getDefaultCollideMask())
        #node.setPythonTag('owner', self.parent)
        cardMaker = CardMaker(self.get_ascii_name() + '-labelcard')
        cardMaker.setFrame(self.label.getFrameActual())
        cardMaker.setColor(0, 0, 0, 0)
        card_node = cardMaker.generate()
        self.label_instance = NodePath(card_node)
        tnp = self.label_instance.attachNewNode(self.label)
        #self.label_instance.setTransparency(TransparencyAttrib.MAlpha)
        #card.setEffect(DecalEffect.make())
        #Using look_at() instead of billboard effect to also rotate the collision solid
        #card.setBillboardPointEye()
        #Using a card holder as look_at() is changing the hpr parameters
        self.instance = NodePath('label-holder')
        self.label_instance.reparentTo(self.instance)
        self.instance.reparentTo(self.context.annotation)
        self.instance_ready = True

        if self.shader is None:
            self.create_shader()
        self.shader.apply(self, self.appearance)
        self.shader.update(self, self.appearance)
        TransparencyBlend.apply(self.appearance.transparency_blend, self.instance)

        self.instance.setCollideMask(GeomNode.getDefaultCollideMask())
        self.instance.set_depth_write(False)
        self.instance.set_color_scale(LColor(1, 1, 1, 1))
        card_node.setPythonTag('owner', self.parent)
        self.look_at = self.instance.attachNewNode("dummy")
Beispiel #36
0
    def __init__(self):
        ShowBase.__init__(self)

        base.disableMouse()

        self.makeAcog = loader.loadModel("phase_5/models/cogdominium/tt_m_ara_cbr_barrelRoom.bam")
        self.makeAcog.reparentTo(render)
        self.stomper1 = (self.makeAcog.find('**/stomper_GRP_01'))
        self.stomper2 = (self.makeAcog.find('**/stomper_GRP_02'))
        self.stomper3 = (self.makeAcog.find('**/stomper_GRP_03'))
        self.stomper4 = (self.makeAcog.find('**/stomper_GRP_04'))
        self.stomper5 = (self.makeAcog.find('**/stomper_GRP_05'))
        self.stomper6 = (self.makeAcog.find('**/stomper_GRP_06'))
        self.stomper7 = (self.makeAcog.find('**/stomper_GRP_07'))
        self.stomper8 = (self.makeAcog.find('**/stomper_GRP_08'))
        self.stomper9 = (self.makeAcog.find('**/stomper_GRP_09'))
        self.stomper10 = (self.makeAcog.find('**/stomper_GRP_10'))
        self.stomper11 = (self.makeAcog.find('**/stomper_GRP_11'))
        self.stomper12 = (self.makeAcog.find('**/stomper_GRP_12'))
        self.stomper3.setPos(0, 0, 18.00)
        self.stomper5.setPos(0, 0, 10.00)
        self.stomper4.setPos(0, 0, 22.00)
        self.stomper2.setPos(0, 0, 7.00)
        self.stomper7.setPos(0, 0, 0)
        self.stomper8.setPos(0, 0, 5.00)
        self.stomper9.setPos(0, 0, 13.00)
        self.stomper10.setPos(0, 0, 10.00)
        self.stomper11.setPos(0, 0, 22.00)
        self.stomper12.setPos(0, 0, 7.00)


        self.music = loader.loadMusic("phase_3/audio/bgm/cco_make_a_cog.wav")
        self.music.play()
        self.music.setLoop(True)

        self.elevator = loader.loadModel("phase_5/models/cogdominium/cogdominiumElevator.bam")
        self.elevator.reparentTo(self.render)
        self.elevator.setY(25.37)
        self.elevator.find('**/floor_light_buttons').removeNode()
        self.rightDoor = (self.elevator.find('**/right_door'))
        self.leftDoor = (self.elevator.find('**/left_door'))
        self.leftDoor.setX(3.50)
        self.rightDoor.setX(-3.50)

        self.skelCog = Actor("phase_5/models/char/cogC_robot-lose-mod.bam", {'neutral': 'phase_3.5/models/char/suitC-neutral.bam',
                                                                             'victory': 'phase_4/models/char/suitC-victory.bam',
                                                                             'walk': 'phase_3.5/models/char/suitC-walk.bam'})
        self.skelCog.reparentTo(self.render)
        self.skelCog.setPos(-16, 0, -4.76)
        self.skelCog.setH(180)




        self.Lawbot = Actor('phase_3.5/models/char/suitC-mod.bam', {'neutral': 'phase_3.5/models/char/suitC-neutral.bam',
                                                                    'victory': 'phase_4/models/char/suitC-victory.bam',
                                                                    'walk': 'phase_3.5/models/char/suitC-walk.bam'})
        self.Lawbot.reparentTo(render)
        self.Lawbot.loop('neutral')
        self.TorsoTex = loader.loadTexture('phase_3.5/maps/l_blazer.jpg')
        self.Lawbot.find('**/torso').setTexture(self.TorsoTex, 1)
        self.ArmTex = loader.loadTexture('phase_3.5/maps/l_sleeve.jpg')
        self.Lawbot.find('**/arms').setTexture(self.ArmTex, 1)
        self.LegTex = loader.loadTexture('phase_3.5/maps/l_leg.jpg')
        self.Lawbot.find('**/legs').setTexture(self.LegTex, 1)
        self.Head = loader.loadModel('phase_3.5/models/char/suitC-heads.bam').find('**/flunky')
        self.headTexture = loader.loadTexture("phase_3.5/maps/bottom-feeder.jpg")
        self.Head.reparentTo(self.Lawbot.find('**/joint_head'))
        self.Lawbot.findAllMatches('**/joint_head').setTexture(self.headTexture, 1)
        self.icon = loader.loadModel('phase_3/models/gui/cog_icons.bam')
        self.icon.reparentTo(render)
        self.icon.reparentTo(self.Lawbot.find('**/joint_attachMeter'))
        self.icon.find('**/MoneyIcon').removeNode()
        self.icon.find('**/cog').removeNode()
        self.icon.find('**/SalesIcon').removeNode()
        self.icon.find('**/CorpIcon').removeNode()
        self.icon.setH(180)
        self.icon.setScale(0.70)
        self.Lawbot.setH(180.00)
        self.Lawbot.hide()


        self.Cashbot = Actor('phase_3.5/models/char/suitC-mod.bam', {'neutral': 'phase_3.5/models/char/suitC-neutral.bam',
                                                                    'victory': 'phase_4/models/char/suitC-victory.bam',
                                                                    'walk': 'phase_3.5/models/char/suitC-walk.bam'})
        self.Cashbot.reparentTo(render)
        self.Cashbot.loop('neutral')
        self.TorsoTex = loader.loadTexture('phase_3.5/maps/m_blazer.jpg')
        self.Cashbot.find('**/torso').setTexture(self.TorsoTex, 1)
        self.ArmTex = loader.loadTexture('phase_3.5/maps/m_sleeve.jpg')
        self.Cashbot.find('**/arms').setTexture(self.ArmTex, 1)
        self.LegTex = loader.loadTexture('phase_3.5/maps/m_leg.jpg')
        self.Cashbot.find('**/legs').setTexture(self.LegTex, 1)
        self.Head = loader.loadModel('phase_3.5/models/char/suitC-heads.bam').find('**/coldcaller')
        self.Head.reparentTo(self.Cashbot.find('**/joint_head'))
        self.icon = loader.loadModel('phase_3/models/gui/cog_icons.bam')
        self.icon.reparentTo(render)
        self.icon.reparentTo(self.Cashbot.find('**/joint_attachMeter'))
        self.icon.find('**/SalesIcon').removeNode()
        self.icon.find('**/cog').removeNode()
        self.icon.find('**/LegalIcon').removeNode()
        self.icon.find('**/CorpIcon').removeNode()
        self.icon.setH(180)
        self.icon.setScale(0.70)
        self.Cashbot.setH(180.00)
        self.Cashbot.hide()

        self.Sellbot = Actor('phase_3.5/models/char/suitC-mod.bam', {'neutral': 'phase_3.5/models/char/suitC-neutral.bam',
                                                                    'victory': 'phase_4/models/char/suitC-victory.bam',
                                                                    'walk': 'phase_3.5/models/char/suitC-walk.bam'})
        self.Sellbot.reparentTo(render)
        self.Sellbot.loop('neutral')
        self.TorsoTex = loader.loadTexture('phase_3.5/maps/s_blazer.jpg')
        self.Sellbot.find('**/torso').setTexture(self.TorsoTex, 1)
        self.ArmTex = loader.loadTexture('phase_3.5/maps/s_sleeve.jpg')
        self.Sellbot.find('**/arms').setTexture(self.ArmTex, 1)
        self.LegTex = loader.loadTexture('phase_3.5/maps/s_leg.jpg')
        self.Sellbot.find('**/legs').setTexture(self.LegTex, 1)
        self.Head = loader.loadModel('phase_3.5/models/char/suitC-heads.bam').find('**/coldcaller')
        self.Head.reparentTo(self.Sellbot.find('**/joint_head'))
        self.Head.reparentTo(self.Sellbot.find('**/joint_head'))
        self.icon = loader.loadModel('phase_3/models/gui/cog_icons.bam')
        self.icon.reparentTo(render)
        self.icon.reparentTo(self.Sellbot.find('**/joint_attachMeter'))
        self.icon.find('**/MoneyIcon').removeNode()
        self.icon.find('**/cog').removeNode()
        self.icon.find('**/LegalIcon').removeNode()
        self.icon.find('**/CorpIcon').removeNode()
        self.icon.setH(180)
        self.icon.setScale(0.70)
        self.Sellbot.setH(180.00)
        self.Sellbot.hide()

        self.Bossbot = Actor('phase_3.5/models/char/suitC-mod.bam',
                             {'neutral': 'phase_3.5/models/char/suitC-neutral.bam',
                              'victory': 'phase_4/models/char/suitC-victory.bam',
                              'walk': 'phase_3.5/models/char/suitC-walk.bam'})
        self.Bossbot.reparentTo(render)
        self.Bossbot.loop('neutral')
        self.TorsoTex = loader.loadTexture('phase_3.5/maps/c_blazer.jpg')
        self.Bossbot.find('**/torso').setTexture(self.TorsoTex, 1)
        self.ArmTex = loader.loadTexture('phase_3.5/maps/c_sleeve.jpg')
        self.Bossbot.find('**/arms').setTexture(self.ArmTex, 1)
        self.LegTex = loader.loadTexture('phase_3.5/maps/c_leg.jpg')
        self.Bossbot.find('**/legs').setTexture(self.LegTex, 1)
        self.Head = loader.loadModel('phase_3.5/models/char/suitC-heads.bam')
        self.Head.find('**/coldcaller').hide()
        self.Head.find('**/gladhander').hide()
        self.Head.find('**/micromanager').hide()
        self.Head.find('**/moneybags').hide()
        self.Head.find('**/tightwad').hide()
        self.Head.reparentTo(self.Bossbot.find('**/joint_head'))
        self.icon = loader.loadModel('phase_3/models/gui/cog_icons.bam')
        self.icon.reparentTo(render)
        self.icon.reparentTo(self.Bossbot.find('**/joint_attachMeter'))
        self.icon.find('**/MoneyIcon').removeNode()
        self.icon.find('**/cog').removeNode()
        self.icon.find('**/LegalIcon').removeNode()
        self.icon.find('**/SalesIcon').removeNode()
        self.icon.setH(180)
        self.icon.setScale(0.70)
        self.Bossbot.setH(180.00)
        self.Bossbot.hide()


        self.Sourcebot = Actor('phase_3.5/models/char/suitC-mod.bam',
                             {'neutral': 'phase_3.5/models/char/suitC-neutral.bam',
                              'victory': 'phase_4/models/char/suitC-victory.bam',
                              'walk': 'phase_3.5/models/char/suitC-walk.bam'})

        self.Sourcebot.reparentTo(render)
        self.Sourcebot.loop('neutral')
        self.TorsoTex = loader.loadTexture('phase_3.5/maps/t_blazer.jpg')
        self.Sourcebot.find('**/torso').setTexture(self.TorsoTex, 1)
        self.ArmTex = loader.loadTexture('phase_3.5/maps/t_sleeve.jpg')
        self.Sourcebot.find('**/arms').setTexture(self.ArmTex, 1)
        self.LegTex = loader.loadTexture('phase_3.5/maps/t_leg.jpg')
        self.Sourcebot.find('**/legs').setTexture(self.LegTex, 1)
        self.Head = loader.loadModel('phase_3.5/models/char/FlairDirector.egg')
        self.headTexture = loader.loadTexture("phase_3.5/maps/flair-director.jpg")
        self.Head.reparentTo(self.Sourcebot.find('**/joint_head'))
        self.Sourcebot.findAllMatches('**/joint_head').setTexture(self.headTexture, 1)
        self.Sourcebot.setH(180.00)
        self.Sourcebot.hide()

        self.Techbot = Actor('phase_3.5/models/char/suitC-mod.bam',
                               {'neutral': 'phase_3.5/models/char/suitC-neutral.bam',
                                'victory': 'phase_4/models/char/suitC-victory.bam',
                                'walk': 'phase_3.5/models/char/suitC-walk.bam'})

        self.Techbot.reparentTo(render)
        self.Techbot.loop('neutral')
        self.TorsoTex = loader.loadTexture('phase_3.5/maps/t_blazer.jpg')
        self.Techbot.find('**/torso').setTexture(self.TorsoTex, 1)
        self.ArmTex = loader.loadTexture('phase_3.5/maps/t_sleeve.jpg')
        self.Techbot.find('**/arms').setTexture(self.ArmTex, 1)
        self.LegTex = loader.loadTexture('phase_3.5/maps/t_leg.jpg')
        self.Techbot.find('**/legs').setTexture(self.LegTex, 1)
        self.Head = loader.loadModel('phase_3.5/models/char/PayrollConvertor.egg')
        self.headTexture = loader.loadTexture("phase_3.5/maps/PayrollConvertor.png")
        self.Head.reparentTo(self.Techbot.find('**/joint_head'))
        self.Head.setPos(0, 0, -0.15)
        self.Head.setScale(0.93)
        self.Techbot.findAllMatches('**/joint_head').setTexture(self.headTexture, 1)
        self.Techbot.setH(180.00)
        self.Techbot.hide()

        self.Pilotbots = Actor('phase_3.5/models/char/suitC-mod.bam',
                             {'neutral': 'phase_3.5/models/char/suitC-neutral.bam',
                              'victory': 'phase_4/models/char/suitC-victory.bam',
                              'walk': 'phase_3.5/models/char/suitC-walk.bam'})

        self.Pilotbots.reparentTo(render)
        self.Pilotbots.loop('neutral')
        self.TorsoTex = loader.loadTexture('phase_3.5/maps/t_blazer.jpg')
        self.Pilotbots.find('**/torso').setTexture(self.TorsoTex, 1)
        self.ArmTex = loader.loadTexture('phase_3.5/maps/t_sleeve.jpg')
        self.Pilotbots.find('**/arms').setTexture(self.ArmTex, 1)
        self.LegTex = loader.loadTexture('phase_3.5/maps/t_leg.jpg')
        self.Pilotbots.find('**/legs').setTexture(self.LegTex, 1)
        self.Head = loader.loadModel('phase_3.5/models/char/ConstructionBot.egg')
        self.headTexture = loader.loadTexture("phase_3.5/maps/Buildbot.png")
        self.Head.reparentTo(self.Pilotbots.find('**/joint_head'))
        self.Head.setPos(0, 0, -0.15)
        self.icon.setH(180)
        self.Pilotbots.findAllMatches('**/joint_head').setTexture(self.headTexture, 1)
        self.Pilotbots.setH(180.00)
        self.Pilotbots.hide()



        #-----Sequences------#

        Walk1 = self.stomper1.posInterval(9.50, Point3(0, 0, 18.00))
        Walk2 = self.stomper1.posInterval(9.50, Point3(0, 0, 0))
        self.stomperPound1 = Sequence(Walk1, Walk2)
        self.stomperPound1.loop()

        Walk1 = self.stomper6.posInterval(9.50, Point3(0, 0, 18.00))
        Walk2 = self.stomper6.posInterval(9.50, Point3(0, 0, 0))
        self.stomperPound2 = Sequence(Walk1, Walk2)
        self.stomperPound2.loop()



        Walk1 = self.stomper3.posInterval(9.50, Point3(0, 0, 0))
        Walk2 = self.stomper3.posInterval(9.50, Point3(0, 0, 18.00))
        self.stomperPound3 = Sequence(Walk1, Walk2)
        self.stomperPound3.loop()

        Walk1 = self.stomper5.posInterval(5.50, Point3(0, 0, 0))
        Walk2 = self.stomper5.posInterval(5.50, Point3(0, 0, 10.00))
        self.stomperPound4 = Sequence(Walk1, Walk2)
        self.stomperPound4.loop()

        Walk1 = self.stomper4.posInterval(5.50, Point3(0, 0, 0))
        Walk2 = self.stomper4.posInterval(5.50, Point3(0, 0, 22.00))
        self.stomperPound5 = Sequence(Walk1, Walk2)
        self.stomperPound5.loop()

        Walk1 = self.stomper2.posInterval(3.50, Point3(0, 0, 0))
        Walk2 = self.stomper2.posInterval(3.50, Point3(0, 0, 7.00))
        self.stomperPound6 = Sequence(Walk1, Walk2)
        self.stomperPound6.loop()

        Walk1 = self.stomper7.posInterval(9.50, Point3(0, 0, 18.00))
        Walk2 = self.stomper7.posInterval(9.50, Point3(0, 0, 0))
        self.stomperPound7 = Sequence(Walk1, Walk2)
        self.stomperPound7.loop()

        Walk1 = self.stomper8.posInterval(5.50, Point3(0, 0, 5.00))
        Walk2 = self.stomper8.posInterval(9.50, Point3(0, 0, 0))
        self.stomperPound8 = Sequence(Walk1, Walk2)
        self.stomperPound8.loop()

        Walk1 = self.stomper9.posInterval(6.50, Point3(0, 0, 0))
        Walk2 = self.stomper9.posInterval(6.50, Point3(0, 0, 13.00))
        self.stomperPound9 = Sequence(Walk1, Walk2)
        self.stomperPound9.loop()

        Walk1 = self.stomper10.posInterval(5.50, Point3(0, 0, 0))
        Walk2 = self.stomper10.posInterval(5.50, Point3(0, 0, 10.00))
        self.stomperPound10 = Sequence(Walk1, Walk2)
        self.stomperPound10.loop()

        Walk1 = self.stomper11.posInterval(5.50, Point3(0, 0, 0))
        Walk2 = self.stomper11.posInterval(5.50, Point3(0, 0, 22.00))
        self.stomperPound11 = Sequence(Walk1, Walk2)
        self.stomperPound11.loop()

        Walk1 = self.stomper12.posInterval(3.50, Point3(0, 0, 0))
        Walk2 = self.stomper12.posInterval(3.50, Point3(0, 0, 7.00))
        self.stomperPound12 = Sequence(Walk1, Walk2)
        self.stomperPound12.loop()



        Walk1 = self.camera.posInterval(2.50, Point3(-20.98, -14.61, 9.74))
        Spin1 = self.camera.hprInterval(1.00, Vec3(321.34, 348.11, 0))
        cogSpin = self.Sellbot.hprInterval(1.50, Vec3(0, 0, 0))
        Walk2 = self.camera.posInterval(5.0, Point3(-20.98, -14.61, 9.74))
        Walk3 = self.camera.posInterval(1.50, Point3(-20.98, 1.40, 7.97))
        Spin2 = self.camera.hprInterval(1.00, Vec3(281.31, 348.11, 0))
        Walk4 = self.camera.posInterval(8.50, Point3(-20.98, 1.40, 7.97))
        Walk5 = self.camera.posInterval(2.50, Point3(0, -19.61, 2.61))
        Spin3 = self.camera.hprInterval(1.00, Vec3(0, 0, 0))
        self.cameraMove = Sequence(Walk1, Spin1, cogSpin, Walk2, Walk3, Spin2, Walk4, Walk5, Spin3)

        Walk1 = self.camera.posInterval(1.50, Point3(0, -77.48, 3.42))
        Spin1 = self.camera.hprInterval(1.00, Vec3(0, 0, 0))
        Walk2 = self.camera.posInterval(2.50, Point3(0, -77.48, 3.42))
        Walk3 = self.camera.posInterval(3.00, Point3(0, -22.48, 3.42))
        Walk4 = self.camera.posInterval(2.00, Point3(0, -22.48, 3.42))
        skelMove1 = self.skelCog.posInterval(0.50, Point3(-16, -0, 0))
        skelMove2 = self.skelCog.posInterval(2.00, Point3(0, -0, 0))
        self.cameraStart = Sequence(Walk1, Spin1, Walk2, Walk3, Walk4, skelMove1, skelMove2)

        Walk1 = self.camera.posInterval(15.50, Point3(6.31, -45.31, 9.27))
        Spin1 = self.camera.hprInterval(0.00, Vec3(337.52, 0, 0))
        Walk2 = self.camera.posInterval(0.00, Point3(6.08, -100.53, 9.27))
        Walk3 = self.camera.posInterval(12.00, Point3(14.07, -77.33, 9.27))
        Walk4 = self.camera.posInterval(0.00, Point3(18.93, -82.36, 25.51))
        Spin2 = self.camera.hprInterval(0.00, Vec3(30.26, 347.91, 0))
        Walk5 = self.camera.posInterval(15.00, Point3(0.44, -51.38, 21.411))
        Spin3 = self.camera.hprInterval(0.00, Vec3(337.52, 0, 0))
        self.cameraIntro = Sequence(Walk1, Spin1, Walk2, Walk3, Walk4, Spin2, Walk5, Spin3)
        self.cameraIntro.loop()



        #----camera---#

        self.camera.setPos(6.31, -82.36, 9.27)
        self.camera.setHpr(35.71, 0, 0)

        #--------Start-up-Menu--------#

        #-----buttons-------#

        #-----texts-------#
        self.logoLeft = OnscreenImage(image='phase_3/maps/cogcitycodeaffix-logo-hor-left[OLD].png', pos=(-0.46, 0, 0.2), scale=(0.7))
        self.logoLeft.setTransparency(TransparencyAttrib.MAlpha)

        self.logoRight = OnscreenImage(image='phase_3/maps/cogcitycodeaffix-logo-hor-right[OLD].png', pos=(0.56, 0, 0.18), scale=(0.7))
        self.logoRight.setTransparency(TransparencyAttrib.MAlpha)

        font = self.loader.loadFont("phase_3/models/fonts/vtRemingtonPortable.ttf")


        text = TextNode("play")
        text.setText("Press F1 to play")
        text.setFont(font)

        self.textNodePath = aspect2d.attachNewNode(text)
        self.textNodePath.setScale(0.09)
        self.textNodePath.setPos(-0.5, 0, -0.7)

        #-----optionText-----------#

        fps = "Show FPS: f2"
        self.textObject1 = OnscreenText(text=fps, pos=(-1.4, -0.97),
        scale=0.09, fg=(1, 0.5, 0.5, 1), align=TextNode.ACenter, mayChange=1)
        self.textObject1.setFont(font)

        fullscreen = "Fullscreen: f2"
        self.textObject2 = OnscreenText(text=fullscreen, pos=(-1.34, -0.88),
                                  scale=0.09, fg=(1, 0.5, 0.5, 1), align=TextNode.ACenter, mayChange=1)
        self.textObject2.setFont(font)

        audio = "Audio: f4"
        self.textObject3 = OnscreenText(text=audio, pos=(-1.48, -0.78),
                                   scale=0.09, fg=(1, 0.5, 0.5, 1), align=TextNode.ACenter, mayChange=1)
        self.textObject3.setFont(font)


        #------doneButton--------#

        font = self.loader.loadFont("phase_3/models/fonts/vtRemingtonPortable.ttf")

        bk_text = ""
        textObject = OnscreenText(text=bk_text, pos=(0.00, 0.73),
                                  scale=0.16, fg=(1, 0.5, 0.5, 1), align=TextNode.ACenter, mayChange=1)
        textObject.setFont(font)
        textObject.setColor(0.3, 0.3, 0.35, 1.0)

        def setText(status):
            if (status):
                bk_text = "Do you want to continue?"
            else:
                bk_text = ""
            textObject.setText(bk_text)


        self.DoneButton = DirectCheckButton(text="Continue", scale=0.12, pos=(0, 0, -0.80), command=setText)
        self.DoneButton.hide()

        #----------key/click-events-------#

        self.acceptOnce("f1-up", self.play)
        self.accept("f2-up", self.frameRate)
Beispiel #37
0
 def load(self):
     from toontown.toonbase import ToontownGlobals
     from panda3d.core import TextNode
     textNode = TextNode('moviedialogue')
     textNode.setTextColor(0, 0, 0, 1)
     textNode.setCardColor(1, 1, 1, 1)
     textNode.setCardAsMargin(0, 0, 0, 0)
     textNode.setCardDecal(True)
     textNode.setWordwrap(27.0)
     textNode.setAlign(TextNode.ACenter)
     textNode.setFont(ToontownGlobals.getToonFont())
     self._dialogueLabel = aspect2d.attachNewNode(textNode)
     self._dialogueLabel.setScale(0.06, 0.06, 0.06)
     self._dialogueLabel.setPos(0.32, 0, -0.75)
     self._dialogueLabel.reparentTo(hidden)
class BossBattleTimer:
    def __init__(self):
        self.text = None
        self.textNodePath = None
        self.flashTrack = None
        self.textSequence = None
        self.startTime = 0
        self.endTime = 0

    def load(self):
        self.text = TextNode('BossBattleTimer')
        self.text.setAlign(TextNode.ACenter)
        self.text.setFlattenFlags(TextNode.FFMedium)
        self.text.setFont(getSuitFont())
        self.text.setTextScale(0.075)
        self.text.setTextColor(*TEXT_WHITE)
        self.textNodePath = aspect2d.attachNewNode(self.text)
        self.textNodePath.reparentTo(base.a2dBottomLeft)
        self.textNodePath.setPos(0.60, 0.0, 0.15)

    def makeFlashTrack(self):
        return Track(
            (0.25, Func(self.text.setTextColor, *TEXT_GREEN)),
            (0.50, Func(self.text.setTextColor, *TEXT_WHITE)),
            (0.75, Func(self.text.setTextColor, *TEXT_GREEN)),
            (1.0, Func(self.text.setTextColor, *TEXT_WHITE)),
            (1.25, Func(self.text.setTextColor, *TEXT_GREEN)),
            (1.50, Func(self.text.setTextColor, *TEXT_WHITE)),
            (1.75, Func(self.text.setTextColor, *TEXT_GREEN)),
            (2.0, Func(self.text.setTextColor, *TEXT_WHITE)),
        )

    def makeGrowShrinkSequence(self):
        return Sequence(
            LerpScaleInterval(self.textNodePath,
                              duration=2.0,
                              scale=1.1,
                              startScale=0.9),
            LerpScaleInterval(self.textNodePath,
                              duration=2.0,
                              scale=0.9,
                              startScale=1.1),
        )

    def destroy(self):
        if self.flashTrack:
            self.flashTrack.finish()
            self.flashTrack = None
        if self.textSequence:
            self.textSequence.finish()
            self.textSequence = None
        if self.text:
            self.text.setText('')
        if self.textNodePath:
            self.textNodePath.removeNode()

    def start(self, startTime):
        self.startTime = startTime
        self.endTime = 0
        if self.textNodePath:
            taskMgr.doMethodLater(0.05, self.updateText,
                                  'updateBossText-%s' % self.startTime)
            self.textSequence = self.makeGrowShrinkSequence()
            self.textSequence.loop()

    def updateText(self, task=None):
        self.text.setText(str(round(time() - self.startTime, 3)) + ' seconds')
        if self.endTime != 0:
            return Task.done
        return Task.again

    def stop(self, endTime):
        self.endTime = endTime
        taskMgr.remove('updateBossText-%s' % self.startTime)
        if self.textNodePath:
            self.text.setText(
                str(round(self.endTime - self.startTime, 3)) + ' seconds')
            self.flashTrack = self.makeFlashTrack()
            self.flashTrack.start()
Beispiel #39
0
    def __init__(self, name):
        NodePath.__init__(self, name)
        DirectObject.__init__(self)
        self.setPythonTag('Sprite', self)

        global SpriteCounter
        SpriteCounter += 1
        self.__id = int(SpriteCounter)

        #- Use PGItem to detect mouse and keyboard input via PGTop (eg, aspect2d, pixel2d, etc)
        self.__pgItem = PGItem(name)
        self.__pgItem.setActive(True)
        self.__pgItemNp = self.attachNewNode(self.__pgItem)

        #- Use TextNode to generate both text and cards for displaying background images
        self.__textNode = TextNode(name)
        self.__textNodeNp = None
        #self.__textNodeNp = self.attachNewNode(self.__textNode)
        #self.__textNode.setCardDecal(True) #- This is what we would do, should Sprite support being non-under PGTop

        self.accept(self.__pgItem.getPressEvent(MouseButton.one()),
                    self.__onMouse, [Sprite.MouseLeftDown])
        self.accept(self.__pgItem.getPressEvent(MouseButton.two()),
                    self.__onMouse, [Sprite.MouseCenterDown])
        self.accept(self.__pgItem.getPressEvent(MouseButton.three()),
                    self.__onMouse, [Sprite.MouseRightDown])
        self.accept(self.__pgItem.getPressEvent(MouseButton.four()),
                    self.__onMouse, [Sprite.MouseFourDown])
        self.accept(self.__pgItem.getPressEvent(MouseButton.five()),
                    self.__onMouse, [Sprite.MouseFiveDown])

        self.accept(self.__pgItem.getReleaseEvent(MouseButton.one()),
                    self.__onMouse, [Sprite.MouseLeftUp])
        self.accept(self.__pgItem.getReleaseEvent(MouseButton.two()),
                    self.__onMouse, [Sprite.MouseCenterUp])
        self.accept(self.__pgItem.getReleaseEvent(MouseButton.three()),
                    self.__onMouse, [Sprite.MouseRightUp])
        self.accept(self.__pgItem.getReleaseEvent(MouseButton.four()),
                    self.__onMouse, [Sprite.MouseFourUp])
        self.accept(self.__pgItem.getReleaseEvent(MouseButton.five()),
                    self.__onMouse, [Sprite.MouseFiveUp])

        self.accept(self.__pgItem.getPressEvent(MouseButton.wheelDown()),
                    self.__onMouse, [Sprite.MouseScrollDown])
        self.accept(self.__pgItem.getPressEvent(MouseButton.wheelUp()),
                    self.__onMouse, [Sprite.MouseScrollUp])

        self.accept(self.__pgItem.getEnterEvent(), self.__onMouse,
                    [Sprite.MouseEnter])
        self.accept(self.__pgItem.getExitEvent(), self.__onMouse,
                    [Sprite.MouseExit])
        self.accept(self.__pgItem.getWithinEvent(), self.__onMouse,
                    [Sprite.MouseWithin])
        self.accept(self.__pgItem.getWithoutEvent(), self.__onMouse,
                    [Sprite.MouseWithout])

        self.__beastDebug = ConfigVariableBool('beast-debug', False).getValue()

        self.__mouseInside = False
        self.__disabled = False

        #- Setup state configuration
        self.__lastStateOptions = None
        self.__state = None
        self.__states = {
            'default': SpriteOptions(),
            'hover': SpriteOptions(),
            'click': SpriteOptions(),
            'focus': SpriteOptions(),
            'disabled': SpriteOptions(),
        }
        self.updateToState('default')
 def loadGUI(self):
     self.gui = loader.loadModel('phase_13/models/parties/trampolineGUI')
     self.gui.reparentTo(base.a2dTopLeft)
     self.gui.setPos(0.115, 0, -1)
     self.gui.hide()
     self.toonIndicator = self.gui.find('**/trampolineGUI_MovingBar')
     jumpLineLocator = self.gui.find('**/jumpLine_locator')
     guiBean = self.gui.find('**/trampolineGUI_GreenJellyBean')
     self.gui.find('**/trampolineGUI_GreenJellyBean').stash()
     self.guiBeans = [ guiBean.instanceUnderNode(jumpLineLocator, self.uniqueName('guiBean%d' % i)) for i in xrange(self.numJellyBeans) ]
     self.guiBeans[-1].setScale(1.5)
     heightTextNode = TextNode(self.uniqueName('TrampolineActivity.heightTextNode'))
     heightTextNode.setFont(ToontownGlobals.getSignFont())
     heightTextNode.setAlign(TextNode.ALeft)
     heightTextNode.setText('0.0')
     heightTextNode.setShadow(0.05, 0.05)
     heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0)
     heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0)
     self.heightText = jumpLineLocator.attachNewNode(heightTextNode)
     self.heightText.setX(0.15)
     self.heightText.setScale(0.1)
     self.heightText.setAlphaScale(0.0)
     self.quitEarlyButtonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui')
     quitEarlyUp = self.quitEarlyButtonModels.find('**//InventoryButtonUp')
     quitEarlyDown = self.quitEarlyButtonModels.find('**/InventoryButtonDown')
     quitEarlyRollover = self.quitEarlyButtonModels.find('**/InventoryButtonRollover')
     self.quitEarlyButton = DirectButton(parent=base.a2dTopRight, relief=None, text=TTLocalizer.PartyTrampolineQuitEarlyButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.7, image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-0.183, 0, -0.4), scale=0.09, command=self.leaveTrampoline)
     self.quitEarlyButton.stash()
     self.flashText = OnscreenText(text='', pos=(0.0, -0.45), scale=0.2, fg=(1.0, 1.0, 0.65, 1.0), align=TextNode.ACenter, font=ToontownGlobals.getSignFont(), mayChange=True)
     self.timer = PartyUtils.getNewToontownTimer()
     self.timer.posInTopRightCorner()
     return
Beispiel #41
0
    def traverse(self, nodePath, dnaStorage):
        root = NodePath('signroot')
        head_root = NodePath('root')
        wantDecalTest = base.config.GetBool('want-sign-decal-test', False)
        x = 0
        for i in range(len(self.text)):
            tn = TextNode('text')
            tn.setText(self.text[i])
            tn.setTextColor(self.color)
            font = dnaStorage.findFont(self.code)
            if font == None:
                raise DNAError.DNAError('Font code %s not found.' % self.code)
            tn.setFont(font)
            if i == 0 and 'b' in self.flags:
                tn.setTextScale(1.5)
            np = root.attachNewNode(tn)
            np.setScale(self.scale)
            np.setDepthWrite(0)
            if i % 2:
                np.setPos(x + self.stumble, 0, self.stomp)
                np.setR(-self.wiggle)
            else:
                np.setPos(x - self.stumble, 0, self.stomp)
                np.setR(self.wiggle)
            x += tn.getWidth() * np.getSx() + self.kern

        for i in range(root.getNumChildren()):
            c = root.getChild(i)
            c.setX(c.getX() - x / 2.0)

        if self.width and self.height:
            for i in range(root.getNumChildren()):
                node = root.getChild(i)
                A = node.getX() / (self.height / 2.0)
                B = self.indent * math.pi / 180.0
                theta = A + B
                d = node.getY()
                x = math.sin(theta) * (self.height / 2.0)
                y = (math.cos(theta) - 1) * (self.height / 2.0)
                radius = math.hypot(x, y)
                if radius != 0:
                    j = (radius + d) / radius
                    x *= j
                    y *= j
                node.setPos(x, 0, y)
                node.setR(node, theta * 180.0 / math.pi)

        collection = root.findAllMatches('**/+TextNode')
        for i in range(collection.getNumPaths()):
            xnp = collection.getPath(i)
            np2 = xnp.getParent().attachNewNode(xnp.node().generate())
            np2.setTransform(xnp.getTransform())
            xnp.removeNode()

        _np = nodePath.attachNewNode(root.node())
        _np.setPosHpr(self.pos, self.hpr)
        if wantDecalTest:
            root.setEffect(DecalEffect.make())
        else:
            _np.setDepthOffset(50)
        self.traverseChildren(_np, dnaStorage)
        _np.flattenStrong()
Beispiel #42
0
class Avatar(Actor, ShadowCaster):
    notify = DirectNotifyGlobal.directNotify.newCategory('Avatar')

    def __init__(self, other=None):
        Actor.__init__(self, None, None, other, flattenable=0, setFinal=1)
        ShadowCaster.__init__(self)
        self.collTube = None
        self.scale = 1.0
        self.height = 0.0
        self.style = None
        self.hpText = None
        self.hpTextGenerator = TextNode('HpTextGenerator')

    def delete(self):
        try:
            self.Avatar_deleted
        except:
            Actor.cleanup(self)
            self.Avatar_deleted = 1
            self.style = None
            self.collTube = None
            self.hpText = None
            self.hpTextGenerator = None
            ShadowCaster.delete(self)
            Actor.delete(self)

    def uniqueName(self, name):
        return 'Avatar-{0}-{1}'.format(id(self), name)

    def getCollisionId(self):
        return self.uniqueName('bodyColl')

    def getAvatarScale(self):
        return self.scale

    def setAvatarScale(self, scale):
        if self.scale != scale:
            self.scale = scale
            self.getGeomNode().setScale(scale)
            self.setHeight(self.height)

    def getHeight(self):
        return self.height

    def setHeight(self, height):
        self.height = height
        if not self.collTube:
            self.initializeBodyCollisions()
        self.collTube.setPointB(0, 0, height - self.getRadius())
        if self.collNodePath:
            self.collNodePath.forceRecomputeBounds()

    def getRadius(self):
        return GameGlobals.AvatarDefaultRadius

    def getStyle(self):
        return self.style

    def setStyle(self, style):
        self.style = style

    def getAirborneHeight(self):
        height = self.getPos(self.shadowPlacer.shadowNodePath)
        return height.getZ() + 0.025

    def initializeBodyCollisions(self):
        self.collTube = CollisionTube(0, 0, 0.5, 0, 0,
                                      self.height - self.getRadius(),
                                      self.getRadius())
        self.collNode = CollisionNode(self.getCollisionId())
        self.collNode.addSolid(self.collTube)
        self.collNodePath = self.attachNewNode(self.collNode)
        self.collNode.setCollideMask(BitmaskGlobals.WallBitmask)

    def showNodePathColl(self):
        self.collNodePath.show()

    def stashBodyCollisions(self):
        if hasattr(self, 'collNodePath'):
            self.collNodePath.stash()

    def unstashBodyCollisions(self):
        if hasattr(self, 'collNodePath'):
            self.collNodePath.unstash()

    def disableBodyCollisions(self):
        if hasattr(self, 'collNodePath'):
            self.collNodePath.removeNode()
            del self.collNodePath
        self.collTube = None

    def showHpText(self, number, bonus=0, scale=1.75):
        if number == 0:
            return

        if self.hpText:
            self.hideHpText()

        self.hpTextGenerator.setFont(GameGlobals.getSignFont())

        if number < 0:
            text = str(number)

            if random.randrange(0, 100) < SILLY_SURGE_CHANCE:
                text += '\n'
                text += random.choice(GameLocalizer.SillySurgeTerms)
        else:
            text = '+' + str(number)

        self.hpTextGenerator.setText(text)
        self.hpTextGenerator.clearShadow()
        self.hpTextGenerator.setAlign(TextNode.ACenter)

        if bonus == 1:
            color = [1, 1, 0, 1]
        elif bonus == 2:
            color = [1, 0.5, 0, 1]
        elif number < 0:
            color = [0.9, 0, 0, 1]
        else:
            color = [0, 0.9, 0, 1]

        self.hpTextGenerator.setTextColor(*color)
        self.hpTextNode = self.hpTextGenerator.generate()
        self.hpText = self.attachNewNode(self.hpTextNode)
        self.hpText.setScale(scale)
        self.hpText.setBillboardPointEye()
        self.hpText.setBin('fixed', 100)

        self.hpText.setPos(0, 0, self.height / 2)

        color[3] = 0

        Sequence(
            self.hpText.posInterval(1.0, (0, 0, self.height + 0.75),
                                    blendType='easeOut'), Wait(0.85),
            self.hpText.colorInterval(0.1, Vec4(*color), 0.1),
            Func(self.hideHpText)).start()

    def hideHpText(self):
        if self.hpText:
            taskMgr.remove(self.uniqueName('hpText'))
            self.hpText.removeNode()
            self.hpText = None
Beispiel #43
0
 def attachHostNameToSign(self, locator):
     if self.hostName == '':
         return
     nameText = TextNode('nameText')
     nameText.setCardAsMargin(0.1, 0.1, 0.1, 0.1)
     nameText.setCardDecal(True)
     nameText.setCardColor(1.0, 1.0, 1.0, 0.0)
     r = 232.0 / 255.0
     g = 169.0 / 255.0
     b = 23.0 / 255.0
     nameText.setTextColor(r, g, b, 1)
     nameText.setAlign(nameText.ACenter)
     nameText.setFont(ToontownGlobals.getBuildingNametagFont())
     nameText.setShadowColor(0, 0, 0, 1)
     nameText.setBin('fixed')
     if TTLocalizer.BuildingNametagShadow:
         nameText.setShadow(*TTLocalizer.BuildingNametagShadow)
     nameWordWrap = 11.0
     nameText.setWordwrap(nameWordWrap)
     scaleMult = 0.48
     houseName = self.hostName
     nameText.setText(houseName)
     textWidth = nameText.getWidth()
     xScale = 1.0 * scaleMult
     if textWidth > nameWordWrap:
         xScale = nameWordWrap / textWidth * scaleMult
     sign_origin = locator
     namePlate = sign_origin.attachNewNode(nameText)
     namePlate.setDepthWrite(0)
     namePlate.setPos(0, 0, 0)
     namePlate.setScale(xScale)
Beispiel #44
0
class PartyPlanner(DirectFrame, FSM):
    notify = DirectNotifyGlobal.directNotify.newCategory('PartyPlanner')

    def __init__(self, doneEvent=None):
        FSM.__init__(self, 'PartyPlannerFSM')
        DirectFrame.__init__(self)
        self.doneEvent = doneEvent
        self.stateArray = [
            'Off', 'Welcome', 'PartyEditor', 'Date', 'Time', 'Invitation',
            'Farewell'
        ]
        self.partyTime = base.cr.toontownTimeManager.getCurServerDateTime()
        self.partyNowTime = base.cr.toontownTimeManager.getCurServerDateTime()
        minutesToNextFifteen = 15 - self.partyTime.minute % 15
        self.cleanPartyTime = self.partyTime + timedelta(
            minutes=minutesToNextFifteen, seconds=-self.partyTime.second)
        self.partyTime = self.cleanPartyTime
        self.guests = []
        self.isPrivate = False
        self.selectedCalendarGuiDay = None
        self.gui = loader.loadModel('phase_4/models/parties/partyPlannerGUI')
        self.partyDuration = timedelta(hours=PartyGlobals.DefaultPartyDuration)
        self.timeTypeToMaxValue = {'hour': 23, 'minute': 59}
        self.timeTypeToChangeAmount = {
            'hour': (1, -1),
            'minute': (15, -15),
            'ampm': (1, -1)
        }
        self.partyInfo = None
        self.asapMinuteRounding = config.GetInt(
            'party-asap-minute-rounding',
            PartyGlobals.PartyPlannerAsapMinuteRounding)
        self.load()
        self.request('Welcome')
        return

    def enterWelcome(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.DISABLED
        self.prevButton.hide()
        self.nextButton['state'] = DirectGuiGlobals.NORMAL
        self.welcomePage.show()
        self.partyPlannerHead.reparentTo(self.welcomePage)
        self.partyPlannerHead.startBlink()
        self.partyPlannerHead.startLookAround()
        self.nametagNP.reparentTo(self.welcomePage)
        self.chatNP.reparentTo(self.welcomePage)

    def exitWelcome(self):
        self.welcomePage.hide()
        self.prevButton.show()
        self.partyPlannerHead.stopBlink()
        self.partyPlannerHead.stopLookAround()

    def enterPartyEditor(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton['state'] = DirectGuiGlobals.DISABLED
        self.nextButton.hide()
        self.partyEditorPage.show()
        self.okWithGroundsGui.doneStatus = ''
        self.partyEditor.request('Idle')

    def exitPartyEditor(self):
        self.partyEditor.request('Hidden')
        self.partyEditorPage.hide()

    def enterGuests(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton.show()
        self.guestPage.show()

    def exitGuests(self):
        self.guests = []
        for friendCheckBox in self.friendList['items']:
            if friendCheckBox['indicatorValue']:
                self.guests.append(friendCheckBox.getPythonTag('id'))

        self.guestPage.hide()

    def enterDate(self, *args):
        self.prevButton.show()
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        if self.selectedCalendarGuiDay is None:
            self.nextButton['state'] = DirectGuiGlobals.DISABLED
            self.nextButton.hide()
            self.makePartyNowButton.show()
        self.datePage.show()
        return

    def exitDate(self):
        self.datePage.hide()
        self.nextButton.show()
        if self.selectedCalendarGuiDay is not None:
            self.partyTime = self.cleanPartyTime
            self.alterPartyTime(year=self.selectedCalendarGuiDay.myDate.year,
                                month=self.selectedCalendarGuiDay.myDate.month,
                                day=self.selectedCalendarGuiDay.myDate.day)
        else:
            self.partyNowTime = self.calcAsapTime()
            self.partyTime = self.partyNowTime
        return

    def calcAsapTime(self):
        curServerTime = base.cr.toontownTimeManager.getCurServerDateTime()
        baseTime = curServerTime
        baseTime = baseTime.replace(baseTime.year,
                                    baseTime.month,
                                    baseTime.day,
                                    baseTime.hour,
                                    baseTime.minute,
                                    second=0,
                                    microsecond=0)
        minute = curServerTime.minute
        remainder = minute % self.asapMinuteRounding
        if remainder:
            baseTime += timedelta(minutes=self.asapMinuteRounding - remainder)
        else:
            baseTime += timedelta(minutes=self.asapMinuteRounding)
        return baseTime

    def enterTime(self, *args):
        self.prevButton.show()
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton.show()
        self.timePage.show()
        self.timePageRecapToontownTimeLabel2[
            'text'] = '%s' % PartyUtils.formatDateTime(self.partyTime)
        self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (
            TTLocalizer.PartyPlannerTimeLocalTime,
            PartyUtils.formatDateTime(self.partyTime, inLocalTime=True))

    def exitTime(self):
        self.timePage.hide()
        self.nextButton.show()

    def enterInvitation(self, *args):
        self.prevButton['state'] = DirectGuiGlobals.NORMAL
        self.nextButton.hide()
        defaultInviteTheme = PartyGlobals.InviteTheme.GenericMale
        if hasattr(base.cr, 'newsManager') and base.cr.newsManager:
            if ToontownGlobals.VICTORY_PARTY_HOLIDAY in base.cr.newsManager.getHolidayIdList(
            ):
                defaultInviteTheme = PartyGlobals.InviteTheme.VictoryParty
            elif ToontownGlobals.KARTING_TICKETS_HOLIDAY in base.cr.newsManager.getHolidayIdList(
            ) or ToontownGlobals.CIRCUIT_RACING_EVENT in base.cr.newsManager.getHolidayIdList(
            ):
                defaultInviteTheme = PartyGlobals.InviteTheme.Racing
            elif ToontownGlobals.VALENTINES_DAY in base.cr.newsManager.getHolidayIdList(
            ):
                defaultInviteTheme = PartyGlobals.InviteTheme.Valentoons
        if self.partyInfo is not None:
            del self.partyInfo
        activityList = self.partyEditor.partyEditorGrid.getActivitiesOnGrid()
        decorationList = self.partyEditor.partyEditorGrid.getDecorationsOnGrid(
        )
        endTime = self.partyTime + self.partyDuration
        self.partyInfo = PartyInfo(0, 0, self.partyTime.year,
                                   self.partyTime.month, self.partyTime.day,
                                   self.partyTime.hour, self.partyTime.minute,
                                   endTime.year, endTime.month, endTime.day,
                                   endTime.hour, endTime.minute,
                                   self.isPrivate, defaultInviteTheme,
                                   activityList, decorationList, 0)
        if self.noFriends or len(self.getInvitees()) == 0:
            self.inviteVisual.setNoFriends(True)
            self.invitationTitleLabel[
                'text'] = TTLocalizer.PartyPlannerConfirmTitleNoFriends
            self.inviteButton[
                'text'] = TTLocalizer.PartyPlannerInviteButtonNoFriends
            self.selectedInviteThemeLabel.stash()
            self.nextThemeButton.stash()
            self.prevThemeButton.stash()
            self.setInviteTheme(defaultInviteTheme)
        else:
            self.inviteVisual.setNoFriends(False)
            self.invitationTitleLabel[
                'text'] = TTLocalizer.PartyPlannerConfirmTitle
            self.inviteButton['text'] = TTLocalizer.PartyPlannerInviteButton
            self.selectedInviteThemeLabel.unstash()
            self.nextThemeButton.unstash()
            self.prevThemeButton.unstash()
            self.setInviteTheme(defaultInviteTheme)
        self.inviteVisual.updateInvitation(base.localAvatar.getName(),
                                           self.partyInfo)
        self.invitationPage.show()
        return

    def __prevTheme(self):
        self.nextThemeButton.show()
        prevTheme = self.currentInvitationTheme - 1
        while prevTheme not in self.inviteThemes:
            prevTheme -= 1
            if prevTheme == self.currentInvitationTheme:
                self.notify.warning('No previous invite theme found.')
                break
            elif prevTheme < 0:
                prevTheme = len(self.inviteVisual.inviteThemesIdToInfo) - 1

        self.setInviteTheme(prevTheme)

    def __nextTheme(self):
        self.prevThemeButton.show()
        nextTheme = self.currentInvitationTheme + 1
        while nextTheme not in self.inviteThemes:
            nextTheme += 1
            if nextTheme == self.currentInvitationTheme:
                self.notify.warning('No next invite theme found.')
                break
            elif nextTheme >= len(self.inviteVisual.inviteThemesIdToInfo):
                nextTheme = 0

        self.setInviteTheme(nextTheme)

    def setInviteTheme(self, themeNumber):
        self.currentInvitationTheme = themeNumber
        self.selectedInviteThemeLabel['text'] = '%s %s (%d/%d)' % (
            self.inviteVisual.inviteThemesIdToInfo[self.currentInvitationTheme]
            [1], TTLocalizer.PartyPlannerInvitationTheme,
            self.inviteThemes.index(self.currentInvitationTheme) + 1,
            len(self.inviteThemes))
        self.partyInfo.inviteTheme = self.currentInvitationTheme
        self.inviteVisual.updateInvitation(base.localAvatar.getName(),
                                           self.partyInfo)

    def exitInvitation(self):
        self.invitationPage.hide()
        self.nextButton.show()

    def enterFarewell(self, goingBackAllowed):
        self.farewellPage.show()
        if goingBackAllowed:
            self.prevButton.show()
        else:
            self.prevButton.hide()
        self.nextButton.hide()
        self.partyPlannerHead.reparentTo(self.farewellPage)
        self.partyPlannerHead.startBlink()
        self.partyPlannerHead.startLookAround()
        self.nametagNP.reparentTo(self.farewellPage)
        self.chatNP.reparentTo(self.farewellPage)

    def exitFarewell(self):
        self.farewellPage.hide()
        self.nextButton.show()
        self.prevButton.show()
        self.partyPlannerHead.stopBlink()
        self.partyPlannerHead.stopLookAround()

    def load(self):
        self.frame = DirectFrame(parent=aspect2d,
                                 geom=self.gui.find('**/background'),
                                 relief=None,
                                 scale=0.85,
                                 pos=(0.05, 0.0, 0.1))
        self.titleScale = TTLocalizer.PPtitleScale
        self._createNavButtons()
        self.welcomePage = self._createWelcomePage()
        self.welcomePage.hide()
        self.datePage = self._createDatePage()
        self.datePage.hide()
        self.timePage = self._createTimePage()
        self.timePage.hide()
        self.guestPage = self._createGuestPage()
        self.guestPage.hide()
        self.partyEditorPage = self._createPartyEditorPage()
        self.partyEditorPage.hide()
        self.invitationPage = self._createInvitationPage()
        self.invitationPage.hide()
        self.farewellPage = self._createFarewellPage()
        self.farewellPage.hide()
        return

    def _createNavButtons(self):
        self.quitButton = DirectButton(
            parent=self.frame,
            relief=None,
            geom=(self.gui.find('**/cancelButton_up'),
                  self.gui.find('**/cancelButton_down'),
                  self.gui.find('**/cancelButton_rollover')),
            command=self.__acceptExit)
        self.nextButton = DirectButton(
            parent=self.frame,
            relief=None,
            geom=(self.gui.find('**/bottomNext_button/nextButton_up'),
                  self.gui.find('**/bottomNext_button/nextButton_down'),
                  self.gui.find('**/bottomNext_button/nextButton_rollover')),
            command=self.__nextItem,
            state=DirectGuiGlobals.DISABLED)
        self.prevButton = DirectButton(
            parent=self.frame,
            relief=None,
            geom=(
                self.gui.find('**/bottomPrevious_button/previousButton_up'),
                self.gui.find('**/bottomPrevious_button/previousButton_down'),
                self.gui.find(
                    '**/bottomPrevious_button/previousButton_rollover')),
            command=self.__prevItem,
            state=DirectGuiGlobals.DISABLED)
        self.currentItem = None
        return

    def __createNametag(self, parent):
        if self.nametagGroup == None:
            self.nametagGroup = NametagGroup()
            self.nametagGroup.setFont(ToontownGlobals.getToonFont())
            self.nametagGroup.setSpeechFont(ToontownGlobals.getToonFont())
            self.nametagGroup.setActive(0)
            self.nametagGroup.setAvatar(self.partyPlannerHead)
            self.nametagGroup.manage(base.marginManager)
            self.nametagGroup.setColorCode(self.nametagGroup.CCNonPlayer)
            self.nametagGroup.getNametag2d().setContents(0)
            self.nametagNode = NametagFloat2d()
            self.nametagNode.setContents(Nametag.CName)
            self.nametagGroup.addNametag(self.nametagNode)
            self.nametagGroup.setName(
                base.cr.partyManager.getPartyPlannerName())
            self.nametagNP = parent.attachNewNode(self.nametagNode)
            nametagPos = self.gui.find(
                '**/step_01_partymanPeteNametag_locator').getPos()
            self.nametagNP.setPosHprScale(nametagPos[0], 0, nametagPos[2], 0,
                                          0, 0, 0.1, 1, 0.1)
            self.chatNode = NametagFloat2d()
            self.chatNode.setContents(Nametag.CSpeech | Nametag.CThought)
            self.nametagGroup.addNametag(self.chatNode)
            self.nametagGroup.setChat(TTLocalizer.PartyPlannerInstructions,
                                      CFSpeech)
            self.chatNP = parent.attachNewNode(self.chatNode)
            chatPos = self.gui.find(
                '**/step_01_partymanPeteText_locator').getPos()
            self.chatNP.setPosHprScale(chatPos[0], 0, chatPos[2], 0, 0, 0,
                                       0.08, 1, 0.08)
        return

    def clearNametag(self):
        if self.nametagGroup != None:
            self.nametagGroup.unmanage(base.marginManager)
            self.nametagGroup.removeNametag(self.nametagNode)
            self.nametagGroup.removeNametag(self.chatNode)
            self.nametagNP.removeNode()
            self.chatNP.removeNode()
            del self.nametagNP
            del self.chatNP
            del self.nametagNode
            del self.chatNode
            self.nametagGroup.setAvatar(NodePath())
            self.nametagGroup.destroy()
            self.nametagGroup = None
        return

    def _createWelcomePage(self):
        self.nametagGroup = None
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerWelcomePage')
        self.welcomeTitleLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerWelcomeTitle,
            pos=self.gui.find('**/title_locator').getPos(),
            scale=self.titleScale)
        self.partyPlannerHead = ToonHead.ToonHead()
        partyPlannerStyle = base.cr.partyManager.getPartyPlannerStyle()
        self.partyPlannerHead.setupHead(partyPlannerStyle, forGui=True)
        self.partyPlannerHead.setPos(
            self.gui.find('**/step_01_partymanPete_locator').getPos())
        animal = partyPlannerStyle.getAnimal()
        if animal == 'cat' or animal == 'pig':
            headScale = 0.4
        else:
            if animal == 'dog' or animal == 'bear':
                headScale = 0.45
            else:
                if animal == 'rabbit':
                    headScale = 0.35
                else:
                    headScale = 0.3
        self.partyPlannerHead.setScale(headScale)
        self.partyPlannerHead.setH(180.0)
        self.partyPlannerHead.reparentTo(page)
        self.__createNametag(page)
        return page

    def _createDatePage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerDatePage')
        self.createDateTitleLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerDateTitle,
            pos=self.gui.find('**/title_locator').getPos(),
            scale=self.titleScale)
        pos = self.gui.find('**/step_06_sendInvitation_locator').getPos()
        self.makePartyNowButton = DirectButton(
            parent=page,
            relief=None,
            geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'),
                  self.gui.find('**/send_rollover')),
            text=TTLocalizer.PartyPlannerPartyNow,
            text_pos=(pos[0], pos[2]),
            text_scale=0.05,
            command=self.__doMakePartyNow)
        curServerDate = base.cr.toontownTimeManager.getCurServerDateTime()
        self.calendarGuiMonth = CalendarGuiMonth(
            page,
            curServerDate,
            scale=0.95,
            pos=(-0.05, 0.0, -0.33),
            dayClickCallback=self._dayClickCallback,
            onlyFutureDaysClickable=True)
        return page

    def __doMakePartyNow(self):
        self.request('Invitation')

    def _dayClickCallback(self, calendarGuiDay):
        self.selectedCalendarGuiDay = calendarGuiDay
        self.nextButton['state'] = DirectGuiGlobals.NORMAL
        self.makePartyNowButton.hide()
        self.nextButton.show()

    def alterPartyTime(self,
                       year=None,
                       month=None,
                       day=None,
                       hour=None,
                       minute=None):
        self.partyTime = datetime(year=self.positiveTime('year', year),
                                  month=self.positiveTime('month', month),
                                  day=self.positiveTime('day', day),
                                  hour=self.positiveTime('hour', hour),
                                  minute=self.positiveTime('minute', minute),
                                  tzinfo=self.partyTime.tzinfo)

    def positiveTime(self, type, amount):
        if amount is None:
            return getattr(self.partyTime, type)
        if type == 'hour' or type == 'minute':
            if amount < 0:
                return self.timeTypeToMaxValue[
                    type] + 1 + self.timeTypeToChangeAmount[type][1]
            if amount > self.timeTypeToMaxValue[type]:
                return 0
        return amount

    def _createTimePage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerTimePage')
        self.createTimeTitleLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerTimeTitle,
            pos=self.gui.find('**/title_locator').getPos(),
            scale=self.titleScale)
        self.clockImage = DirectFrame(
            parent=page,
            relief=None,
            geom=self.gui.find('**/toontownTime_background'))
        self.timePageToontownLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerTimeToontown,
            pos=self.gui.find('**/step_03_toontown_locator').getPos(),
            scale=0.15,
            text_fg=(1.0, 0.0, 0.0, 1.0),
            text_font=ToontownGlobals.getSignFont())
        self.timePageTimeLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerTimeTime,
            pos=self.gui.find('**/step_03_time_locator').getPos(),
            scale=0.15,
            text_fg=(1.0, 0.0, 0.0, 1.0),
            text_font=ToontownGlobals.getSignFont())
        self.timePageRecapLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerTimeRecap,
            pos=self.gui.find('**/step_03_partyDateAndTime_locator').getPos(),
            scale=0.09)
        self.timePageRecapToontownTimeLabel1 = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerTimeToontownTime,
            pos=self.gui.find('**/step_03_toontownTime_locator').getPos(),
            scale=0.06)
        self.timePageRecapToontownTimeLabel2 = DirectLabel(
            parent=page,
            relief=None,
            text='%s' % PartyUtils.formatDateTime(self.partyTime),
            pos=self.gui.find(
                '**/step_03_toontownDateAndTime_loactor').getPos(),
            textMayChange=True,
            scale=0.06)
        self.timePageRecapLocalTimeLabel = DirectLabel(
            parent=page,
            relief=None,
            text='%s%s' %
            (TTLocalizer.PartyPlannerTimeLocalTime,
             PartyUtils.formatDateTime(self.partyTime, inLocalTime=True)),
            pos=self.gui.find('**/step_03_localDateAndTime_loactor').getPos(),
            textMayChange=True,
            scale=0.06,
            text_fg=(1.0, 0.0, 0.0, 1.0))
        self.timeInputHourLabel, self.timeInputHourUpButton, self.timeInputHourDownButton = self.getTimeWidgets(
            page, 'hour')
        self.timeInputMinuteLabel, self.timeInputMinuteUpButton, self.timeInputMinuteDownButton = self.getTimeWidgets(
            page, 'minute')
        self.timeInputAmPmLabel, self.timeInputAmPmUpButton, self.timeInputAmPmDownButton = self.getTimeWidgets(
            page, 'ampm')
        self.timePagecolonLabel = DirectLabel(
            parent=page,
            relief=None,
            text=':',
            pos=self.gui.find('**/step_03_colon_locator').getPos(),
            scale=0.15)
        return page

    def getTimeWidgets(self, page, type):
        if type == 'ampm':
            data = self.getCurrentAmPm()
        else:
            data = getattr(self.partyTime, type)
            if data == 0 and type == 'minute':
                data = '00'
            else:
                if type == 'hour':
                    data = data % 12
                    if data == 0:
                        data = 12
                data = '%d' % data
        label = DirectLabel(parent=page,
                            relief=None,
                            text='%s' % data,
                            textMayChange=True,
                            pos=self.gui.find('**/step_03_%s_locator' %
                                              type).getPos(),
                            scale=0.12)

        def changeValue(self, amount):
            if type == 'ampm':
                self.alterPartyTime(hour=(self.partyTime.hour + 12) % 24)
                newAmount = self.getCurrentAmPm()
                label['text'] = newAmount
            else:
                if type == 'hour':
                    newAmount = getattr(self.partyTime, type) + amount
                    newAmount = newAmount % 12
                    if self.timeInputAmPmLabel[
                            'text'] == TTLocalizer.PartyTimeFormatMeridiemPM:
                        newAmount = newAmount % 12 + 12
                    self.alterPartyTime(hour=newAmount)
                else:
                    if type == 'minute':
                        newAmount = getattr(self.partyTime, type) + amount
                        self.alterPartyTime(minute=newAmount)
                    else:
                        PartyPlanner.notify.error(
                            'Invalid type for changeValue in PartyPlanner: %s'
                            % type)
                newAmount = getattr(self.partyTime, type)
                if newAmount < 10 and type == 'minute':
                    label['text'] = '0%d' % newAmount
                else:
                    if type == 'hour':
                        newAmount = newAmount % 12
                        if newAmount == 0:
                            newAmount = 12
                    label['text'] = '%d' % newAmount
            self.timePageRecapToontownTimeLabel2[
                'text'] = '%s' % PartyUtils.formatDateTime(self.partyTime)
            self.timePageRecapLocalTimeLabel['text'] = '%s%s' % (
                TTLocalizer.PartyPlannerTimeLocalTime,
                PartyUtils.formatDateTime(self.partyTime, inLocalTime=True))

        upButton = DirectButton(
            parent=page,
            relief=None,
            geom=(self.gui.find('**/%sButtonUp_up' % type),
                  self.gui.find('**/%sButtonUp_down' % type),
                  self.gui.find('**/%sButtonUp_rollover' % type)),
            command=changeValue,
            extraArgs=[self, self.timeTypeToChangeAmount[type][0]])
        downButton = DirectButton(
            parent=page,
            relief=None,
            geom=(self.gui.find('**/%sButtonDown_up' % type),
                  self.gui.find('**/%sButtonDown_down' % type),
                  self.gui.find('**/%sButtonDown_rollover' % type)),
            command=changeValue,
            extraArgs=[self, self.timeTypeToChangeAmount[type][1]])
        return (label, upButton, downButton)

    def getCurrentAmPm(self):
        if self.partyTime.hour < 12:
            return TTLocalizer.PartyTimeFormatMeridiemAM
        return TTLocalizer.PartyTimeFormatMeridiemPM

    def _createGuestPage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerGuestPage')
        self.guestTitleLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerGuestTitle,
            pos=self.gui.find('**/title_locator').getPos(),
            scale=self.titleScale)
        self.guestBackgroundLabel = DirectLabel(
            parent=page,
            relief=None,
            image=self.gui.find('**/guestListBackground_flat'),
            scale=(1.2, 1.0, 1.0))
        self.friendList = ScrolledFriendList(page,
                                             self.gui,
                                             makeItemsCheckBoxes=True)
        if len(base.localAvatar.friendsList) == 0:
            self.noFriends = True
        else:
            self.noFriends = False
            for friendPair in base.localAvatar.friendsList:
                self.friendList.addFriend(determineFriendName(friendPair),
                                          friendPair[0])

            self.friendList.scrollTo(0)
        pos = self.gui.find('**/step_04_partyWillBe_locator').getPos()
        self.publicPrivateLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerPublicPrivateLabel,
            text_align=TextNode.ACenter,
            text_scale=0.065,
            pos=pos)
        self.publicDescriptionLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerPublicDescription,
            text_align=TextNode.ACenter,
            text_scale=TTLocalizer.PPpbulicDescriptionLabel,
            pos=(pos[0] - 0.52, pos[1], pos[2]))
        self.publicDescriptionLabel.stash()
        self.privateDescriptionLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerPrivateDescription,
            text_align=TextNode.ACenter,
            text_scale=TTLocalizer.PPprivateDescriptionLabel,
            pos=(pos[0] + 0.55, pos[1], pos[2]))
        self.privateDescriptionLabel.stash()
        pos = self.gui.find('**/step_04_public_locator').getPos()
        self.publicButton = DirectButton(
            parent=page,
            relief=None,
            geom=(self.gui.find('**/publicButton_up'),
                  self.gui.find('**/publicButton_down'),
                  self.gui.find('**/publicButton_rollover'),
                  self.gui.find('**/publicButton_inactive')),
            text=TTLocalizer.PartyPlannerPublic,
            text_pos=(pos[0], pos[2]),
            text_scale=TTLocalizer.PPpublicButton,
            command=self.__doTogglePublicPrivate)
        self.publicButton['state'] = DirectGuiGlobals.DISABLED
        self.publicButton.bind(DirectGuiGlobals.ENTER, self.__enterPublic)
        self.publicButton.bind(DirectGuiGlobals.EXIT, self.__exitPublic)
        pos = self.gui.find('**/step_04_private_locator').getPos()
        self.privateButton = DirectButton(
            parent=page,
            relief=None,
            geom=(self.gui.find('**/privateButton_up'),
                  self.gui.find('**/privateButton_down'),
                  self.gui.find('**/privateButton_rollover'),
                  self.gui.find('**/privateButton_inactive')),
            text=TTLocalizer.PartyPlannerPrivate,
            text_pos=(pos[0], pos[2]),
            text_scale=TTLocalizer.PPprivateButton,
            command=self.__doTogglePublicPrivate)
        self.privateButton.bind(DirectGuiGlobals.ENTER, self.__enterPrivate)
        self.privateButton.bind(DirectGuiGlobals.EXIT, self.__exitPrivate)
        self.checkAllButton = DirectButton(
            parent=page,
            relief=None,
            geom=(self.gui.find('**/checkAllButton_up'),
                  self.gui.find('**/checkAllButton_down'),
                  self.gui.find('**/checkAllButton_rollover')),
            command=self.__doCheckAll)
        self.uncheckAllButton = DirectButton(
            parent=page,
            relief=None,
            geom=(self.gui.find('**/uncheckAllButton_up'),
                  self.gui.find('**/uncheckAllButton_down'),
                  self.gui.find('**/uncheckAllButton_rollover')),
            command=self.__doUncheckAll)
        return page

    def __doCheckAll(self):
        for friendBox in self.friendList['items']:
            friendBox['indicatorValue'] = True

    def __doUncheckAll(self):
        for friendBox in self.friendList['items']:
            friendBox['indicatorValue'] = False

    def __enterPrivate(self, mouseEvent):
        self.privateDescriptionLabel.unstash()

    def __exitPrivate(self, mouseEvent):
        self.privateDescriptionLabel.stash()

    def __enterPublic(self, mouseEvent):
        self.publicDescriptionLabel.unstash()

    def __exitPublic(self, mouseEvent):
        self.publicDescriptionLabel.stash()

    def __doTogglePublicPrivate(self):
        if self.isPrivate:
            self.isPrivate = False
            self.privateButton['state'] = DirectGuiGlobals.NORMAL
            self.publicButton['state'] = DirectGuiGlobals.DISABLED
        else:
            self.isPrivate = True
            self.privateButton['state'] = DirectGuiGlobals.DISABLED
            self.publicButton['state'] = DirectGuiGlobals.NORMAL

    def _createPartyEditorPage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerEditorPage')
        self.LayoutTitleLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerEditorTitle,
            pos=self.gui.find('**/title_locator').getPos() +
            Point3(0.0, 0.0, 0.075),
            scale=self.titleScale)
        self.costLabel = DirectLabel(parent=page,
                                     pos=(-0.74, 0.0, 0.17),
                                     relief=None,
                                     text=TTLocalizer.PartyPlannerTotalCost %
                                     0,
                                     text_align=TextNode.ACenter,
                                     scale=TTLocalizer.PPcostLabel,
                                     textMayChange=True)
        self.partyGridBackground = DirectFrame(
            parent=page, relief=None, geom=self.gui.find('**/partyGrid_flat'))
        self.partyGroundsLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerPartyGrounds,
            text_font=ToontownGlobals.getSignFont(),
            text_fg=VBase4(1.0, 0.0, 0.0, 1.0),
            text_scale=TTLocalizer.PPpartyGroundsLabel,
            pos=self.gui.find('**/step_05_partyGrounds_text_locator').getPos(),
            scale=0.1)
        self.activityBackground = DirectFrame(
            parent=page,
            relief=None,
            geom=self.gui.find('**/activitiesDecorations_flat1'),
            pos=(0.0, 0.0, 0.04))
        pos = self.gui.find('**/step_05_instructions_locator').getPos()
        self.instructionLabel = DirectLabel(
            parent=page,
            relief=None,
            text=' ',
            text_pos=(pos[0], pos[2]),
            text_scale=TTLocalizer.PPinstructionLabel,
            textMayChange=True,
            geom=self.gui.find('**/instructions_flat'))
        self.elementTitleLabel = DirectLabel(
            parent=page,
            relief=None,
            text=' ',
            pos=self.gui.find(
                '**/step_05_activitiesName_text_locator').getPos() +
            Point3(0.0, 0.0, 0.04),
            text_scale=TTLocalizer.PPelementTitleLabel,
            textMayChange=True)
        self.elementPriceNode = TextNode('ElementPrice')
        self.elementPriceNode.setAlign(TextNode.ALeft)
        self.elementPriceNode.setTextColor(0.0, 0.0, 0.0, 1.0)
        self.elementPriceNode.setFont(ToontownGlobals.getToonFont())
        self.elementPrice = page.attachNewNode(self.elementPriceNode)
        self.elementPrice.setScale(TTLocalizer.PPelementPriceNode)
        self.elementPrice.setPos(
            self.gui.find('**/step_05_activityPrice_text_locator').getPos() +
            Point3(-0.02, 0.0, 0.04))
        self.elementDescriptionNode = TextNode('ElementDescription')
        self.elementDescriptionNode.setAlign(TextNode.ACenter)
        self.elementDescriptionNode.setWordwrap(8)
        self.elementDescriptionNode.setFont(ToontownGlobals.getToonFont())
        self.elementDescriptionNode.setTextColor(0.0, 0.0, 0.0, 1.0)
        self.elementDescription = page.attachNewNode(
            self.elementDescriptionNode)
        self.elementDescription.setScale(TTLocalizer.PPelementDescription)
        self.elementDescription.setPos(
            self.gui.find(
                '**/step_05_activityDescription_text_locator').getPos() +
            Point3(0.0, 0.0, 0.04))
        self.totalMoney = base.localAvatar.getTotalMoney()
        catalogGui = loader.loadModel('phase_5.5/models/gui/catalog_gui')
        self.beanBank = DirectLabel(parent=page,
                                    relief=None,
                                    text=str(self.totalMoney),
                                    text_align=TextNode.ARight,
                                    text_scale=0.075,
                                    text_fg=(0.95, 0.95, 0, 1),
                                    text_shadow=(0, 0, 0, 1),
                                    text_pos=(0.495, -0.53),
                                    text_font=ToontownGlobals.getSignFont(),
                                    textMayChange=True,
                                    image=catalogGui.find('**/bean_bank'),
                                    image_scale=(0.65, 0.65, 0.65),
                                    scale=0.9,
                                    pos=(-0.75, 0.0, 0.6))
        catalogGui.removeNode()
        del catalogGui
        self.accept(localAvatar.uniqueName('moneyChange'), self.__moneyChange)
        self.accept(localAvatar.uniqueName('bankMoneyChange'),
                    self.__moneyChange)
        self.partyEditor = PartyEditor(self, page)
        self.partyEditor.request('Hidden')
        pos = self.gui.find('**/step_05_add_text_locator').getPos()
        self.elementBuyButton = DirectButton(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerBuy,
            text_pos=(pos[0], pos[2]),
            text_scale=TTLocalizer.PPelementBuyButton,
            geom=(self.gui.find('**/add_up'), self.gui.find('**/add_down'),
                  self.gui.find('**/add_rollover')),
            geom3_color=VBase4(0.5, 0.5, 0.5, 1.0),
            textMayChange=True,
            pos=(0.0, 0.0, 0.04),
            command=self.partyEditor.buyCurrentElement)
        self.okWithPartyGroundsLayoutEvent = 'okWithPartyGroundsLayoutEvent'
        self.accept(self.okWithPartyGroundsLayoutEvent,
                    self.okWithPartyGroundsLayout)
        self.okWithGroundsGui = TTDialog.TTGlobalDialog(
            dialogName=self.uniqueName('PartyEditorOkGui'),
            doneEvent=self.okWithPartyGroundsLayoutEvent,
            message=TTLocalizer.PartyPlannerOkWithGroundsLayout,
            style=TTDialog.YesNo,
            okButtonText=OTPLocalizer.DialogYes,
            cancelButtonText=OTPLocalizer.DialogNo)
        self.okWithGroundsGui.doneStatus = ''
        self.okWithGroundsGui.hide()
        return page

    def okWithPartyGroundsLayout(self):
        self.okWithGroundsGui.hide()
        if self.okWithGroundsGui.doneStatus == 'ok':
            self.__nextItem()

    def setNextButtonState(self, enabled):
        if enabled:
            self.nextButton['state'] = DirectGuiGlobals.NORMAL
            self.nextButton.show()
        else:
            self.nextButton['state'] = DirectGuiGlobals.DISABLED
            self.nextButton.hide()

    def _createInvitationPage(self):
        self.__handleHolidays()
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerInvitationPage')
        self.invitationTitleLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerConfirmTitle,
            textMayChange=True,
            pos=self.gui.find('**/title_locator').getPos(),
            scale=self.titleScale)
        self.invitationBackground = DirectFrame(
            parent=page,
            relief=None,
            geom=self.gui.find('**/invitationBackground'))
        self.inviteVisual = InviteVisual(page)
        self.selectedInviteThemeLabel = DirectLabel(
            parent=page,
            relief=None,
            pos=self.gui.find('**/step_06_theme_locator').getPos(),
            text='',
            text_scale=0.06,
            textMayChange=True)
        self.nextThemeButton = DirectButton(
            parent=page,
            relief=None,
            geom=(self.gui.find('**/topNext_button/nextButton_up'),
                  self.gui.find('**/topNext_button/nextButton_down'),
                  self.gui.find('**/topNext_button/nextButton_rollover')),
            command=self.__nextTheme)
        self.prevThemeButton = DirectButton(
            parent=page,
            relief=None,
            geom=(self.gui.find('**/topPrevious_button/previousButton_up'),
                  self.gui.find('**/topPrevious_button/previousButton_down'),
                  self.gui.find(
                      '**/topPrevious_button/previousButton_rollover')),
            command=self.__prevTheme)
        pos = self.gui.find('**/step_06_sendInvitation_locator').getPos()
        self.inviteButton = DirectButton(
            parent=page,
            relief=None,
            geom=(self.gui.find('**/send_up'), self.gui.find('**/send_down'),
                  self.gui.find('**/send_rollover')),
            text=TTLocalizer.PartyPlannerInviteButton,
            textMayChange=True,
            text_scale=0.05,
            text_pos=(pos[0], pos[2]),
            command=self.__handleComplete)
        return page

    def __handleHolidays(self):
        self.inviteThemes = range(len(PartyGlobals.InviteTheme))
        if hasattr(base.cr, 'newsManager') and base.cr.newsManager:
            holidayIds = base.cr.newsManager.getHolidayIdList()
            if ToontownGlobals.VALENTINES_DAY not in holidayIds:
                self.inviteThemes.remove(PartyGlobals.InviteTheme.Valentoons)
            if ToontownGlobals.VICTORY_PARTY_HOLIDAY not in holidayIds:
                self.inviteThemes.remove(PartyGlobals.InviteTheme.VictoryParty)
            if ToontownGlobals.WINTER_DECORATIONS not in holidayIds and ToontownGlobals.WACKY_WINTER_DECORATIONS not in holidayIds:
                self.inviteThemes.remove(PartyGlobals.InviteTheme.Winter)

    def _createFarewellPage(self):
        page = DirectFrame(self.frame)
        page.setName('PartyPlannerFarewellPage')
        self.confirmTitleLabel = DirectLabel(
            parent=page,
            relief=None,
            text=TTLocalizer.PartyPlannerConfirmationAllOkTitle,
            textMayChange=True,
            pos=self.gui.find('**/title_locator').getPos(),
            scale=self.titleScale)
        pos = self.gui.find('**/step_07_close_text_locator').getPos()
        self.closePlannerButton = DirectButton(
            parent=page,
            relief=None,
            geom=(self.gui.find('**/close_up'), self.gui.find('**/close_down'),
                  self.gui.find('**/close_rollover')),
            text=TTLocalizer.PartyPlannerClosePlanner,
            text_scale=0.055,
            text_pos=(pos[0], pos[2]),
            command=self.__acceptExit)
        return page

    def close(self):
        self.ignore('addPartyResponseReceived')
        self.ignore(localAvatar.uniqueName('moneyChange'))
        self.ignore(localAvatar.uniqueName('bankMoneyChange'))
        self.timeInputHourUpButton.destroy()
        self.timeInputHourDownButton.destroy()
        self.timeInputMinuteUpButton.destroy()
        self.timeInputMinuteDownButton.destroy()
        self.timeInputAmPmUpButton.destroy()
        self.timeInputAmPmDownButton.destroy()
        self.privateButton.destroy()
        self.publicButton.destroy()
        self.makePartyNowButton.destroy()
        self.checkAllButton.destroy()
        self.uncheckAllButton.destroy()
        self.elementBuyButton.destroy()
        self.nextThemeButton.destroy()
        self.prevThemeButton.destroy()
        self.inviteButton.destroy()
        self.closePlannerButton.destroy()
        self.ignore(self.okWithPartyGroundsLayoutEvent)
        if hasattr(self, 'okWithGroundsGui'):
            self.okWithGroundsGui.cleanup()
            del self.okWithGroundsGui
        if hasattr(self, 'frame') and not self.frame.isEmpty():
            messenger.send(self.doneEvent)
            self.hide()
            self.cleanup()
            self.friendList.removeAndDestroyAllItems()
            self.friendList.destroy()
            self.calendarGuiMonth.destroy()
            self.frame.destroy()
        self.partyPlannerHead.delete()
        self.partyPlannerHead.removeNode()
        self.clearNametag()
        self.partyEditor.request('Cleanup')
        self.partyEditor = None
        self.destroy()
        del self
        return

    def __handleComplete(self):
        self.inviteButton['state'] = DirectGuiGlobals.DISABLED
        self.prevButton['state'] = DirectGuiGlobals.DISABLED
        endTime = self.partyTime + self.partyDuration
        hostId = base.localAvatar.doId
        self.partyActivities = self.partyEditor.partyEditorGrid.getActivitiesOnGrid(
        )
        decorations = self.partyEditor.partyEditorGrid.getDecorationsOnGrid()
        invitees = self.getInvitees()
        self.accept('addPartyResponseReceived', self.processAddPartyResponse)
        base.cr.partyManager.sendAddParty(
            hostId, self.partyTime.strftime('%Y-%m-%d %H:%M:%S'),
            endTime.strftime('%Y-%m-%d %H:%M:%S'), self.isPrivate,
            self.currentInvitationTheme, self.partyActivities, decorations,
            invitees)

    def getInvitees(self):
        invitees = []
        for friendBox in self.friendList['items']:
            if friendBox['indicatorValue']:
                invitees.append(friendBox.getPythonTag('id'))

        return invitees

    def processAddPartyResponse(self, hostId, errorCode):
        PartyPlanner.notify.debug(
            'processAddPartyResponse : hostId=%d errorCode=%s' %
            (hostId, PartyGlobals.AddPartyErrorCode.getString(errorCode)))
        goingBackAllowed = False
        if errorCode == PartyGlobals.AddPartyErrorCode.AllOk:
            goingBackAllowed = False
            self.confirmTitleLabel[
                'text'] = TTLocalizer.PartyPlannerConfirmationAllOkTitle
            if self.noFriends or len(self.getInvitees()) == 0:
                confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkTextNoFriends
            else:
                confirmRecapText = TTLocalizer.PartyPlannerConfirmationAllOkText
        else:
            if errorCode == PartyGlobals.AddPartyErrorCode.ValidationError:
                self.confirmTitleLabel[
                    'text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle
                confirmRecapText = TTLocalizer.PartyPlannerConfirmationValidationErrorText
            else:
                if errorCode == PartyGlobals.AddPartyErrorCode.DatabaseError:
                    self.confirmTitleLabel[
                        'text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle
                    confirmRecapText = TTLocalizer.PartyPlannerConfirmationDatabaseErrorText
                else:
                    if errorCode == PartyGlobals.AddPartyErrorCode.TooManyHostedParties:
                        goingBackAllowed = False
                        self.confirmTitleLabel[
                            'text'] = TTLocalizer.PartyPlannerConfirmationErrorTitle
                        confirmRecapText = TTLocalizer.PartyPlannerConfirmationTooManyText
        self.nametagGroup.setChat(confirmRecapText, CFSpeech)
        self.request('Farewell', goingBackAllowed)

    def __acceptExit(self):
        PartyPlanner.notify.debug('__acceptExit')
        if hasattr(self, 'frame'):
            self.hide()
            messenger.send(self.doneEvent)

    def __nextItem(self):
        messenger.send('wakeup')
        if self.state == 'PartyEditor' and self.okWithGroundsGui.doneStatus != 'ok':
            self.okWithGroundsGui.show()
            return
        if self.state == 'PartyEditor' and self.noFriends:
            self.request('Date')
            self.selectedCalendarGuiDay = None
            self.calendarGuiMonth.clearSelectedDay()
            return
        if self.state == 'Guests':
            self.selectedCalendarGuiDay = None
            self.calendarGuiMonth.clearSelectedDay()
        if self.state == 'Time':
            if self.partyTime < base.cr.toontownTimeManager.getCurServerDateTime(
            ):
                self.okChooseFutureTimeEvent = 'okChooseFutureTimeEvent'
                self.acceptOnce(self.okChooseFutureTimeEvent,
                                self.okChooseFutureTime)
                self.chooseFutureTimeDialog = TTDialog.TTGlobalDialog(
                    dialogName=self.uniqueName('chooseFutureTimeDialog'),
                    doneEvent=self.okChooseFutureTimeEvent,
                    message=TTLocalizer.PartyPlannerChooseFutureTime,
                    style=TTDialog.Acknowledge)
                self.chooseFutureTimeDialog.show()
                return
        self.requestNext()
        return

    def okChooseFutureTime(self):
        if hasattr(self, 'chooseFutureTimeDialog'):
            self.chooseFutureTimeDialog.cleanup()
            del self.chooseFutureTimeDialog
        if hasattr(self, 'okChooseFutureTimeEvent'):
            self.ignore(self.okChooseFutureTimeEvent)

    def __prevItem(self):
        messenger.send('wakeup')
        if self.state == 'Date' and self.noFriends:
            self.request('PartyEditor')
            return
        if self.state == 'Invitation' and self.selectedCalendarGuiDay is None:
            self.request('Guests')
            return
        self.requestPrev()
        return

    def __moneyChange(self, newMoney):
        if hasattr(self, 'totalMoney'):
            self.totalMoney = base.localAvatar.getTotalMoney()
        if hasattr(self, 'beanBank'):
            self.beanBank['text'] = str(int(self.totalMoney))
    flag.reparent_to(OSSteerManager.get_global_ptr().get_reference_node_path())
    flagWave = app.loader.load_model("flag_oga-wave.egg")
    flagWave.reparent_to(flag)
    auto_bind(flag.node(), flagAnims)
    flagAnims.get_anim(0).loop(True)
    return flag


if __name__ == '__main__':

    msg = "'capture_the_flag'"
    app = startFramework(msg)

    # # here is room for your own code
    # print some help to screen
    text = TextNode("Help")
    text.set_text(
        msg + "\n\n"
        "- press \"d\" to toggle debug drawing\n"
        "- press \"a\"/\"e\" to add a seeker/enemy\n"
        "- press \"h\" to set home base center\n"
        "- press \"s\"/\"shift-s\" to increase/decrease last inserted vehicle's max speed\n"
        "- press \"f\"/\"shift-f\" to increase/decrease last inserted vehicle's max force\n"
        "- press \"o\"/\"shift-o\" to add/remove obstacle\n")
    textNodePath = app.aspect2d.attach_new_node(text)
    textNodePath.set_pos(-1.25, 0.0, 0.8)
    textNodePath.set_scale(0.035)

    # create a steer manager; set root and mask to manage 'kinematic' vehicles
    steerMgr = OSSteerManager(app.render, mask)
Beispiel #46
0
class Cog(DirectObject):
    def __init__(self, name, dept, suit, head, handColor, height, minLevel,
                 maxLevel):
        self.name = name
        self.dept = dept
        self.head = head
        self.headObj = None
        self.headAccessory = head.getAccessory()
        self.suit = suit
        self.handColor = handColor
        self.height = height
        self.level = random.randint(minLevel, maxLevel)
        self.minLevel = minLevel
        self.maxLevel = maxLevel
        self.version = 1
        self.hit = False
        self.isDefeated = False
        self.healthBar = None
        self.healthCondition = 0

    def generate(self, isSkeleton=False, isWaiter=False):
        self.isSkeleton = isSkeleton
        self.isWaiter = isWaiter
        self.suit.setupSuit(self.dept.getDept(), self.handColor, isSkeleton,
                            isWaiter)
        self.suit.generate()
        self.cog = self.suit.getActor()
        self.cog.setPythonTag('Cog', self)
        self.cog.setName(self.name)
        self.cog.flattenStrong()
        if (self.level % 12 != 0):
            self.hp = (self.level + 1) * (self.level + 2)
        else:
            self.hp = (self.level / 12) * 200
        self.maxHp = self.hp
        if not isSkeleton:
            self.headObj = self.head.generate(self.headAccessory)
            self.head.getHead().reparentTo(self.cog.find('**/joint_head'))
        self.corpMedallion = self.cog.find('**/Medallion')
        self.generateHealthBar()
        self.createNameTag()
        if not self.isSkeleton:
            if (self.headObj.getChildren().size() == 0
                    and self.head.hasAccessory()):
                self.head.attemptAccessoryFix()

    def createNameTag(self):
        try:
            if (self.nameTag):
                self.nameTagPath.removeNode()
        except:
            pass
        self.nameTag = TextNode("NameTag")
        dept = self.dept.getGameDept()
        name = self.name
        if self.isSkeleton:
            name = "Skelecog"
        if (self.version == 1):
            self.nameTag.setText('%s\n%s\nLevel %s' % (name, dept, self.level))
        else:
            self.nameTag.setText('%s\n%s\nLevel %s v%s.0' %
                                 (name, dept, self.level, self.version))
        cogFont = Globals.getFont('vtRemingtonPortable.ttf')
        self.nameTag.setFont(cogFont)
        self.nameTagPath = render.attachNewNode(self.nameTag)
        self.nameTagPath.reparentTo(self.cog.find('**/joint_nameTag'))
        self.nameTagPath.setBillboardPointEye(0)
        head = self.head.getHead()
        jointPos = self.cog.find('**/joint_head').getPos(render)
        if (head != None):
            min, max = head.getTightBounds()
            size = max - min
            zPos = head.getPos(render).getZ() - size.getZ()
            pos = head.getPos(render).getZ() + size.getZ() + 2.4
        else:
            pos = jointPos.getZ() + 2.4
        self.nameTagPath.setZ(pos)
        self.nameTag.setAlign(TextNode.ACenter)
        self.nameTag.setCardColor(0.8, 0.8, 0.8, 0.5)
        self.nameTag.setCardAsMargin(0, 0, 0, -0.2)
        self.nameTag.setCardDecal(True)
        self.nameTag.setTextColor(0.2, 0.2, 0.2, 1.0)
        self.nameTagPath.setScale(0.35)

    def playAnim(self, anim, playRate, loop):
        if (loop):
            ActorInterval(self.cog, anim, playRate=playRate).loop()
        else:
            ActorInterval(self.cog, anim, playRate=playRate)

    def updateHealthBar(self):
        health = float(float(self.hp) / float(self.maxHp))
        if health < 1:
            self.corpMedallion.hide()
            self.healthBar.show()
        if health > 0.95:
            condition = 0
        elif health > 0.7:
            condition = 1
        elif health > 0.3:
            condition = 2
        elif health > 0.05:
            condition = 3
        elif health > 0:
            condition = 4
        else:
            condition = 5
        if (self.healthCondition != condition):
            if (condition == 4):
                blinkTask = Task.loop(Task(self.__blinkRed), Task.pause(0.75),
                                      Task(self.__blinkGray), Task.pause(0.1))
                base.taskMgr.add(blinkTask, 'blink-task')
            elif (condition == 5):
                if (self.healthCondition == 4):
                    base.taskMgr.remove('blink-task')
                if (self.isDefeated == False):
                    blinkTask = Task.loop(Task(self.__blinkRed),
                                          Task.pause(0.25),
                                          Task(self.__blinkGray),
                                          Task.pause(0.1))
                    base.taskMgr.add(blinkTask, 'blink-task')
                    self.isDefeated = True
                    if not self.cog.hasPythonTag("Support"):
                        roundInstance = render.getPythonTag('Round')
                        wave = roundInstance.getCurrentWave()
                        wave.setCogsDefeated(wave.getCogsDefeated() + 1)
                    base.taskMgr.doMethodLater(1.5, self.setDefeated,
                                               'Set Cog Defeated')
            else:
                self.healthBar.setColor(healthColors[condition], 1)
                self.healthBarGlow.setColor(healthGlowColors[condition], 1)
            self.healthCondition = condition

    def __blinkRed(self, task):
        self.healthBar.setColor(healthColors[3], 1)
        self.healthBarGlow.setColor(healthGlowColors[3], 1)
        return Task.done

    def __blinkGray(self, task):
        if not self.healthBar:
            return
        self.healthBar.setColor(healthColors[4], 1)
        self.healthBarGlow.setColor(healthGlowColors[4], 1)
        return Task.done

    def generateHealthBar(self):
        self.removeHealthBar()
        model = loader.loadModel('phase_3.5/models/gui/matching_game_gui.bam')
        meter = model.find("**/minnieCircle")
        meter.setScale(3)
        meter.setH(180)
        meter.setColor(healthColors[0])
        joint = self.cog.find('**/joint_attachMeter')
        meter.reparentTo(joint)
        self.healthBar = meter
        glow = loader.loadModel('phase_3.5/models/props/glow.bam')
        glow.reparentTo(self.healthBar)
        glow.setScale(0.28)
        glow.setPos(-0.005, 0.01, 0.015)
        glow.setColor(healthGlowColors[0])
        meter.flattenLight()
        self.healthBarGlow = glow
        self.healthCondition = 0
        self.healthBar.hide()
        if (self.isSkeleton):
            self.healthBar.setPos(0, 0.1, 0)

    def removeHealthBar(self):
        if self.healthBar:
            self.healthBar.removeNode()
            self.healthBar = None
        if self.healthCondition == 4 or self.healthCondition == 5:
            taskMgr.remove(self.uniqueName('blink-task'))
        self.healthCondition = 0
        return

    def setVersion(self, version):
        self.version = version

    def getVersion(self):
        return self.version

    def destroyCog(self):
        self.suit.getShadow().deleteDropShadow()
        self.cog.cleanup()
        self.cog.removeNode()

    def setDefeated(self, task):
        def playSound(sound):
            SoundBank.getSound(sound).play()

        def generateReward(pos, hpr):
            reward = random.choice([True, False])
            if (reward):
                dropMgr = render.getPythonTag('DropManager')
                drop = dropMgr.generateRandomDrop()
                drop.reparentTo(render)
                drop.setPos(pos.getX(), pos.getY(), pos.getZ() + 0.8)

        if self.cog.isEmpty():
            return
        pos = self.cog.getPos()
        hpr = self.cog.getHpr()
        head = copy.copy(self.cog.find('**/Head'))
        self.destroyCog()
        self.suit.setupLoseSuit(self.dept.getDept(), self.handColor,
                                self.isSkeleton, self.isWaiter)
        self.suit.generate()
        render.getPythonTag('WorldCollisions').addCogGroundCollision(
            ent=self.suit.getActor())
        self.cog = self.suit.getActor()
        if not self.isSkeleton:
            head.reparentTo(self.cog.find("**/joint_head"))
        self.cog.setPos(pos)
        self.cog.setHpr(hpr)
        self.cog.reparentTo(render)
        self.cog.play('lose')
        Sequence(
            Wait(1.5),
            Func(playSound, 'cog_laugh'),
            Wait(3.5),
            Func(playSound, 'cog_explode'),
            Func(generateReward, pos, hpr),
            Wait(8),
            Func(self.destroyCog),
        ).start()
        return Task.done

    def setLevel(self, level):
        self.level = level
        self.hp = (level + 1) * (level + 2)
        self.maxHp = self.hp

    def setHealth(self, hp):
        self.hp = hp
        self.updateHealthBar()

    def getHealth(self):
        return self.hp

    def setHit(self, flag):
        self.hit = flag

    def wasHit(self):
        return self.hit

    def stopAnim(self, anim):
        self.cog.stop()

    def cleanUp(self):
        self.cog.cleanup()
        self.cog.removeNode()
        del self

    def getName(self):
        return self.name

    def getDept(self):
        return self.dept

    def getHead(self):
        return self.headObj

    def isDefeated(self):
        return self.isDefeated

    def getHeight(self):
        return self.height

    def getLevelCurve(self):
        return [self.minLevel, self.maxLevel]

    def getLevel(self):
        return self.level

    def getCog(self):
        return self.cog
Beispiel #47
0
    def __init__(self, name='NONAME', id=None):
        NetEnt.__init__(self, id)
        self.node = NetNodePath(PandaNode('A Character'))
        self.node.setTag('ID', str(self.id))
        if not id:
            self.spawn()
        self.node.reparentTo(render)
        CharacterPool.add(self)
        self.xVelocity = 0
        self.yVelocity = 0
        self.vertVelocity = None
        self.duck = False
        self.deltaT = 0

        self.sprite = Sprite2d('resources/origsprite.png',
                               rows=3,
                               cols=8,
                               rowPerFace=(0, 1, 2, 1))
        self.sprite.createAnim('walk', (1, 0, 2, 0))
        self.sprite.createAnim('kick', (5, 6, 7, 6, 5))
        self.sprite.node.reparentTo(self.node)

        # set up character's name label
        self.nameNode = NodePath(TextNode('Char Name'))
        self.nameNode.node().setText(name)
        self.nameNode.node().setAlign(TextNode.ACenter)
        self.nameNode.node().setCardColor(0.2, 0.2, 0.2, 0.5)
        self.nameNode.node().setCardAsMargin(0, 0, 0, 0)
        self.nameNode.node().setCardDecal(True)
        self.nameNode.setZ(1.7)
        self.nameNode.setScale(0.2)
        self.nameNode.setBillboardAxis()
        self.nameNode.reparentTo(self.node)

        # collision
        self.collisionHandler = CollisionHandlerQueue()
        # set up 'from' collision - for detecting char hitting things
        self.fromCollider = self.node.attachNewNode(
            CollisionNode('fromCollider'))
        self.fromCollider.node().addSolid(CollisionRay(0, 0, 2, 0, 0, -1))
        self.fromCollider.node().setIntoCollideMask(BITMASK_EMPTY)
        self.fromCollider.node().setFromCollideMask(BITMASK_TERRAIN)
        if SHOW_COLLISIONS:
            self.fromCollider.show()
        Character.collisionTraverser.addCollider(self.fromCollider,
                                                 self.collisionHandler)

        # set up 'into' collision - for detecting things hitting char
        self.intoCollider = self.node.attachNewNode(
            CollisionNode('intoCollider'))
        self.intoCollider.node().addSolid(
            CollisionTube(0, 0, 0.5, 0, 0, 1, 0.5))
        self.intoCollider.node().setIntoCollideMask(BITMASK_CHARACTER)
        self.intoCollider.node().setFromCollideMask(BITMASK_EMPTY)
        if SHOW_COLLISIONS:
            self.intoCollider.show()

        self.oldPosition = self.node.getPos()
        self.collisionZ = self.node.getZ()

        # set up weapons
        self.sinceShoot = 10

        # speculated client history - used for input prediction
        self.posHistory = []
Beispiel #48
0
class PandaVis(ShowBase):
    """Base class for all visualizations with panda3d"""
    def __init__(self, rendering: bool):
        """
        Constructor

        :param rendering: boolean indicating whether to use RenderPipeline or default Panda3d as visualization-module.
        """
        super().__init__(self)
        self.dir = Filename.fromOsSpecific(
            pyrado.PANDA_ASSETS_DIR).getFullpath()

        # Initialize RenderPipeline
        if rendering:
            sys.path.insert(0, pyrado.RENDER_PIPELINE_DIR)
            from rpcore import RenderPipeline

            self.render_pipeline = RenderPipeline()
            self.render_pipeline.pre_showbase_init()
            self.render_pipeline.set_loading_screen_image(
                osp.join(self.dir, "logo.png"))
            self.render_pipeline.settings["pipeline.display_debugger"] = False
            self.render_pipeline.create(self)
            self.render_pipeline.daytime_mgr.time = "17:00"
        else:
            self.render_pipeline = None

        # Activate antialiasing
        self.render.setAntialias(AntialiasAttrib.MAuto)

        # Set window properties
        self.windowProperties = WindowProperties()
        self.windowProperties.setForeground(True)
        self.windowProperties.setTitle("Experiment")

        # Set background color
        self.setBackgroundColor(1, 1, 1)

        # Configuration of the lighting
        self.directionalLight1 = DirectionalLight("directionalLight")
        self.directionalLightNP1 = self.render.attachNewNode(
            self.directionalLight1)
        self.directionalLightNP1.setHpr(0, -8, 0)
        self.render.setLight(self.directionalLightNP1)

        self.directionalLight2 = DirectionalLight("directionalLight")
        self.directionalLightNP2 = self.render.attachNewNode(
            self.directionalLight2)
        self.directionalLightNP2.setHpr(180, -20, 0)
        self.render.setLight(self.directionalLightNP2)

        self.ambientLight = AmbientLight("ambientLight")
        self.ambientLightNP = self.render.attachNewNode(self.ambientLight)
        self.ambientLight.setColor((0.1, 0.1, 0.1, 1))
        self.render.setLight(self.ambientLightNP)

        # Create a text node displaying the physic parameters on the top left of the screen
        self.text = TextNode("parameters")
        self.textNodePath = aspect2d.attachNewNode(self.text)
        self.text.setTextColor(0, 0, 0, 1)  # black
        self.textNodePath.setScale(0.07)
        self.textNodePath.setPos(-1.9, 0, 0.9)

        # Configure trace
        self.trace = LineSegs()
        self.trace.setThickness(3)
        self.trace.setColor(0.8, 0.8, 0.8)  # light grey
        self.lines = self.render.attachNewNode("Lines")
        self.last_pos = None

        # Adds one instance of the update function to the task-manager, thus initializes the animation
        self.taskMgr.add(self.update, "update")

    def update(self, task: Task):
        """
        Updates the visualization with every call.

        :param task: Needed by panda3d task manager.
        :return Task.cont: indicates that task should be called again next frame.
        """
        return Task.cont

    def reset(self):
        """
        Resets the the visualization to a certain state, so that in can be run again. Removes the trace.
        """
        self.lines.getChildren().detach()
        self.last_pos = None

    def draw_trace(self, point):
        """
        Draws a line from the last point to the current point

        :param point: Current position of pen. Needs 3 value vector.
        """
        # Check if trace initialized
        if self.last_pos:
            # Set starting point of new line
            self.trace.moveTo(self.last_pos)

        # Draw line to that point
        self.trace.drawTo(point)

        # Save last position of pen
        self.last_pos = point

        # Show drawing
        self.trace_np = NodePath(self.trace.create())
        self.trace_np.reparentTo(self.lines)
 def loadSign(self):
     actNameForSign = self.activityName
     if self.activityId == PartyGlobals.ActivityIds.PartyJukebox40:
         actNameForSign = PartyGlobals.ActivityIds.getString(
             PartyGlobals.ActivityIds.PartyJukebox)
     elif self.activityId == PartyGlobals.ActivityIds.PartyDance20:
         actNameForSign = PartyGlobals.ActivityIds.getString(
             PartyGlobals.ActivityIds.PartyDance)
     self.sign = self.root.attachNewNode('%sSign' % self.activityName)
     self.signModel = self.party.defaultSignModel.copyTo(self.sign)
     self.signFlat = self.signModel.find('**/sign_flat')
     self.signFlatWithNote = self.signModel.find('**/sign_withNote')
     self.signTextLocator = self.signModel.find('**/signText_locator')
     textureNodePath = getPartyActivityIcon(self.party.activityIconsModel,
                                            actNameForSign)
     textureNodePath.setPos(0.0, -0.02, 2.2)
     textureNodePath.setScale(2.35)
     textureNodePath.copyTo(self.signFlat)
     textureNodePath.copyTo(self.signFlatWithNote)
     text = TextNode('noteText')
     text.setTextColor(0.2, 0.1, 0.7, 1.0)
     text.setAlign(TextNode.ACenter)
     text.setFont(OTPGlobals.getInterfaceFont())
     text.setWordwrap(10.0)
     text.setText('')
     self.noteText = self.signFlatWithNote.attachNewNode(text)
     self.noteText.setPosHpr(self.signTextLocator, 0.0, 0.0, 0.2, 0.0, 0.0,
                             0.0)
     self.noteText.setScale(0.2)
     self.signFlatWithNote.stash()
     self.signTextLocator.stash()
Beispiel #50
0
    def text(self, text):
        self.raw_text = text

        # clear stuff
        for img in self.images:
            destroy(img)
        self.images.clear()

        for tn in self.text_nodes:
            tn.remove_node()
        self.text_nodes.clear()

        # check if using tags
        if (not self.use_tags or self.text == self.start_tag
                or self.text == self.end_tag or not self.start_tag in text
                or not self.end_tag in text):

            self.create_text_section(text)
            self.align()
            return

        # parse tags
        text = self.start_tag + self.end_tag + str(
            text)  # start with empty tag for alignemnt to work?
        sections = list()
        section = ''
        tag = self.start_tag + 'default' + self.end_tag
        temp_text_node = TextNode('temp_text_node')
        temp_text_node.setFont(self.font)
        x = 0
        y = 0

        i = 0
        while i < len(text):
            char = text[i]
            if char == '\n':
                sections.append([section, tag, x, y])
                section = ''
                y -= 1
                x = 0
                i += 1

            elif char == self.start_tag:  # find tag
                sections.append([section, tag, x, y])
                x += temp_text_node.calcWidth(section)
                section = ''

                tag = ''
                for j in range(len(text) - i):
                    tag += text[i + j]
                    if text[i + j] == self.end_tag and len(tag) > 0:
                        i += j + 1
                        break
            else:
                section += char
                i += 1

        sections.append([section, tag, x, y])

        for i, s in enumerate(sections):
            tag = s[1]
            # move the text after image one space right
            if tag.startswith(self.start_tag + 'image:'):
                for f in sections:
                    if f[3] == s[3] and f[2] > s[2]:
                        f[2] += .5

                s[2] += .5

            self.create_text_section(text=s[0], tag=s[1], x=s[2], y=s[3])

        self.align()
class InteractiveAnimatedProp(GenericAnimatedProp.GenericAnimatedProp, FSM.FSM):
    ZoneToIdles = {}
    ZoneToIdleIntoFightAnims = {}
    ZoneToFightAnims = {}
    ZoneToVictoryAnims = {}
    ZoneToSadAnims = {}
    IdlePauseTime = base.config.GetFloat('prop-idle-pause-time', 0.0)
    HpTextGenerator = TextNode('HpTextGenerator')
    BattleCheerText = '+'

    def __init__(self, node, holidayId = -1):
        FSM.FSM.__init__(self, 'InteractiveProp-%s' % str(node))
        self.holidayId = holidayId
        self.numIdles = 0
        self.numFightAnims = 0
        self.idleInterval = None
        self.battleCheerInterval = None
        self.sadInterval = None
        self.victoryInterval = None
        self.lastIdleAnimName = ''
        self.lastIdleTime = 0
        self.curIval = None
        self.okToStartNextAnim = False
        cellIndexStr = node.getTag('DNACellIndex')
        self.cellIndex = ord(cellIndexStr)
        self.origAnimNameToSound = {}
        self.lastPlayingAnimPhase = 0
        self.buildingsMakingMeSad = set()
        GenericAnimatedProp.GenericAnimatedProp.__init__(self, node)
        return

    def delete(self):
        self.exit()
        GenericAnimatedProp.GenericAnimatedProp.delete(self)
        self.idleInterval = None
        self.battleCheerInterval = None
        self.sadInterval = None
        self.victoryInterval = None
        return

    def getCellIndex(self):
        return self.cellIndex

    def playBattleCheerAnim(self):
        self.node.loop('battleCheer')

    def setupActor(self, node):
        if self.hoodId in self.ZoneToIdles:
            self.numIdles = len(self.ZoneToIdles[self.hoodId])
        if self.hoodId in self.ZoneToFightAnims:
            self.numFightAnims = len(self.ZoneToFightAnims[self.hoodId])
        self.idleInterval = None
        anim = node.getTag('DNAAnim')
        self.trashcan = Actor.Actor(node, copy=0)
        self.trashcan.reparentTo(node)
        self.soundPos = node.getPos()
        animDict = {}
        animDict['anim'] = '%s/%s' % (self.path, anim)
        for i in range(self.numIdles):
            baseAnim = self.ZoneToIdles[self.hoodId][i]
            if isinstance(baseAnim, tuple):
                baseAnim = baseAnim[0]
            animStr = self.path + '/' + baseAnim
            animKey = 'idle%d' % i
            animDict[animKey] = animStr
            settleName = self.getSettleName(i)
            if settleName:
                settleStr = self.path + '/' + settleName
                settleKey = 'settle%d' % i
                animDict[settleKey] = settleStr

        for i in range(self.numFightAnims):
            animStr = self.path + '/' + self.ZoneToFightAnims[self.hoodId][i]
            animKey = 'fight%d' % i
            animDict[animKey] = animStr

        if self.hoodId in self.ZoneToIdleIntoFightAnims:
            animStr = self.path + '/' + self.ZoneToIdleIntoFightAnims[self.hoodId]
            animKey = 'idleIntoFight'
            animDict[animKey] = animStr
        if self.hoodId in self.ZoneToIdleIntoFightAnims:
            animStr = self.path + '/' + self.ZoneToVictoryAnims[self.hoodId]
            animKey = 'victory'
            animDict[animKey] = animStr
        if self.hoodId in self.ZoneToSadAnims:
            animStr = self.path + '/' + self.ZoneToSadAnims[self.hoodId]
            animKey = 'sad'
            animDict[animKey] = animStr
        self.trashcan.loadAnims(animDict)
        self.trashcan.pose('anim', 0)
        self.node = self.trashcan
        self.idleInterval = self.createIdleInterval()
        self.battleCheerInterval = self.createBattleCheerInterval()
        self.victoryInterval = self.createVictoryInterval()
        self.sadInterval = self.createSadInterval()
        return

    def createIdleInterval(self):
        result = Sequence()
        if self.numIdles >= 3:
            numberOfAnimsAbove2 = self.numIdles - 2
            for rareIdle in range(2, self.numIdles):
                for i in range(2):
                    result.append(ActorInterval(self.node, 'idle0'))
                    result.append(Wait(self.IdlePauseTime))
                    result.append(ActorInterval(self.node, 'idle1'))
                    result.append(Wait(self.IdlePauseTime))

                result.append(ActorInterval(self.node, 'idle%d' % rareIdle))
                result.append(Wait(self.IdlePauseTime))

        else:
            for i in range(self.numIdles):
                result.append(ActorInterval(self.node, 'idle%d' % i))

        self.notify.debug('idle interval=%s' % result)
        return result

    def createBattleCheerText(self):
        self.HpTextGenerator.setFont(ToontownGlobals.getSignFont())
        self.HpTextGenerator.setText(self.BattleCheerText)
        self.HpTextGenerator.clearShadow()
        self.HpTextGenerator.setAlign(TextNode.ACenter)
        r = 0
        g = 0
        b = 1
        a = 1
        self.HpTextGenerator.setTextColor(r, g, b, a)
        self.hpTextNode = self.HpTextGenerator.generate()
        self.hpText = self.node.attachNewNode(self.hpTextNode)
        self.hpText.setScale(1)
        self.hpText.setBillboardPointEye()
        self.hpText.setBin('fixed', 100)
        self.hpText.setPos(0, 0, 4)
        self.hpText.hide()

    def createBattleCheerInterval(self):
        result = Sequence()
        for i in range(self.numFightAnims):
            animKey = 'fight%d' % i
            animAndSoundIval = self.createAnimAndSoundIval(animKey)
            origAnimName = self.node.getAnimFilename(animKey).split('/')[-1]
            if self.hasOverrideIval(origAnimName):
                result.append(self.getOverrideIval(origAnimName))
            elif self.hasSpecialIval(origAnimName):
                result.append(Parallel(animAndSoundIval, self.getSpecialIval(origAnimName)))
            else:
                result.append(animAndSoundIval)

        self.createBattleCheerText()
        battleCheerTextIval = Sequence(Func(self.hpText.show), self.hpText.posInterval(duration=4.0, pos=Vec3(0, 0, 7), startPos=(0, 0, 3)), Func(self.hpText.hide))
        ivalWithText = Parallel(battleCheerTextIval, result)
        return ivalWithText

    def createSadInterval(self):
        result = Sequence()
        if self.hoodId in self.ZoneToSadAnims:
            result = self.createAnimAndSoundIval('sad')
        return result

    def hasSpecialIval(self, origAnimName):
        return False

    def getSpecialIval(self, origAnimName):
        return Sequence()

    def hasOverrideIval(self, origAnimName):
        return False

    def getOverrideIval(self, origAnimName):
        return Sequence()

    def createVictoryInterval(self):
        result = Sequence()
        if self.hoodId in self.ZoneToVictoryAnims:
            animAndSoundIval = self.createAnimAndSoundIval('victory')
            result.append(animAndSoundIval)
        return result

    def enter(self):
        GenericAnimatedProp.GenericAnimatedProp.enter(self)
        if base.config.GetBool('props-buff-battles', True):
            self.notify.debug('props buff battles is true')
            if base.cr.newsManager.isHolidayRunning(self.holidayId):
                self.notify.debug('holiday is running, doing idle interval')
                self.node.stop()
                self.node.pose('idle0', 0)
                if base.config.GetBool('interactive-prop-random-idles', 1):
                    self.requestIdleOrSad()
                else:
                    self.idleInterval.loop()
            else:
                self.notify.debug('holiday is NOT running, doing nothing')
                self.node.stop()
                self.node.pose('idle0', 0)
        else:
            self.notify.debug('props do not buff battles')
            self.node.stop()
            self.node.pose('idle0', 0)

    def exit(self):
        self.okToStartNextAnim = False
        self.notify.debug('%s %d okToStartNextAnim=%s' % (self, self.visId, self.okToStartNextAnim))
        GenericAnimatedProp.GenericAnimatedProp.exit(self)
        self.request('Off')

    def requestIdleOrSad(self):
        if not hasattr(self, 'node') or not self.node:
            self.notify.warning("requestIdleOrSad  returning hasattr(self,'node')=%s" % hasattr(self, 'node'))
            return
        if self.buildingsMakingMeSad:
            self.request('Sad')
        else:
            self.request('DoIdleAnim')

    def enterDoIdleAnim(self):
        self.notify.debug('enterDoIdleAnim numIdels=%d' % self.numIdles)
        self.okToStartNextAnim = True
        self.notify.debug('%s %d okToStartNextAnim=%s' % (self, self.visId, self.okToStartNextAnim))
        self.startNextIdleAnim()

    def exitDoIdleAnim(self):
        self.notify.debug('exitDoIdlesAnim numIdles=%d' % self.numIdles)
        self.okToStartNextAnim = False
        self.notify.debug('%s %d okToStartNextAnim=%s' % (self, self.visId, self.okToStartNextAnim))
        self.calcLastIdleFrame()
        self.clearCurIval()

    def calcLastIdleFrame(self):
        if self.curIval and self.curIval.ivals:
            firstIval = self.curIval.ivals[0]
            if isinstance(firstIval, ActorInterval):
                self.lastIdleFrame = firstIval.getCurrentFrame()
                self.lastIdleAnimName = firstIval.animName
            elif isinstance(firstIval, Parallel):
                for testIval in firstIval.ivals:
                    if isinstance(firstIval, ActorInterval):
                        self.lastIdleTime = testIval.getT()
                        self.lastIdleAnimName = testIval.animName
                        break

    def chooseIdleAnimToRun(self):
        result = self.numIdles - 1
        if base.config.GetBool('randomize-interactive-idles', True):
            pairs = []
            for i in range(self.numIdles):
                reversedChance = self.numIdles - i - 1
                pairs.append((math.pow(2, reversedChance), i))


        else:
            result = self.lastPlayingAnimPhase + 1
            if result >= len(self.ZoneToIdles[self.hoodId]):
                result = 0
        return result

    def startNextIdleAnim(self):
        self.notify.debug('startNextAnim self.okToStartNextAnim=%s' % self.okToStartNextAnim)
        if not hasattr(self, 'node') or not self.node:
            self.notify.warning("startNextIdleAnim returning hasattr(self,'node')=%s" % hasattr(self, 'node'))
            return
        self.curIval = None
        if self.okToStartNextAnim:
            self.notify.debug('got pass okToStartNextAnim')
            whichAnim = self.chooseIdleAnimToRun()
            if self.visId == localAvatar.zoneId:
                self.notify.debug('whichAnim=%s' % whichAnim)
                if __dev__:
                    self.notify.info('whichAnim=%s %s' % (whichAnim, self.getOrigIdleAnimName(whichAnim)))
            self.lastPlayingAnimPhase = whichAnim
            self.curIval = self.createIdleAnimSequence(whichAnim)
            self.notify.debug('starting curIval of length %s' % self.curIval.getDuration())
            self.curIval.start()
        else:
            self.curIval = Wait(10)
            self.notify.debug('false self.okToStartNextAnim=%s' % self.okToStartNextAnim)
        return

    def createIdleAnimAndSoundInterval(self, whichIdleAnim, startingTime = 0):
        animIval = self.node.actorInterval('idle%d' % whichIdleAnim, startTime=startingTime)
        animIvalDuration = animIval.getDuration()
        origAnimName = self.ZoneToIdles[self.hoodId][whichIdleAnim]
        if isinstance(origAnimName, tuple):
            origAnimName = origAnimName[0]
        soundIval = self.createSoundInterval(origAnimName, animIvalDuration)
        soundIvalDuration = soundIval.getDuration()
        if self.hasSpecialIval(origAnimName):
            specialIval = self.getSpecialIval(origAnimName)
            idleAnimAndSound = Parallel(animIval, soundIval, specialIval)
        else:
            idleAnimAndSound = Parallel(animIval, soundIval)
        return idleAnimAndSound

    def createIdleAnimSequence(self, whichIdleAnim):
        dummyResult = Sequence(Wait(self.IdlePauseTime))
        if not hasattr(self, 'node') or not self.node:
            self.notify.warning("createIdleAnimSequence returning dummyResult hasattr(self,'node')=%s" % hasattr(self, 'node'))
            return dummyResult
        idleAnimAndSound = self.createIdleAnimAndSoundInterval(whichIdleAnim)
        result = Sequence(idleAnimAndSound, Wait(self.IdlePauseTime), Func(self.startNextIdleAnim))
        if isinstance(self.ZoneToIdles[self.hoodId][whichIdleAnim], tuple) and len(self.ZoneToIdles[self.hoodId][whichIdleAnim]) > 2:
            info = self.ZoneToIdles[self.hoodId][whichIdleAnim]
            origAnimName = info[0]
            minLoop = info[1]
            maxLoop = info[2]
            settleAnim = info[3]
            minPauseTime = info[4]
            maxPauseTime = info[5]
            numberOfLoops = random.randrange(minLoop, maxLoop + 1)
            pauseTime = random.randrange(minPauseTime, maxPauseTime + 1)
            result = Sequence()
            for i in range(numberOfLoops):
                result.append(idleAnimAndSound)

            if self.getSettleName(whichIdleAnim):
                result.append(self.node.actorInterval('settle%d' % whichIdleAnim))
            result.append(Wait(pauseTime))
            result.append(Func(self.startNextIdleAnim))
        return result

    def gotoFaceoff(self):
        self.notify.debugStateCall(self)
        if base.cr.newsManager.isHolidayRunning(self.holidayId):
            self.request('Faceoff')
        else:
            self.notify.debug('not going to faceoff because holiday %d is not running' % self.holidayId)

    def gotoBattleCheer(self):
        self.notify.debugStateCall(self)
        if base.cr.newsManager.isHolidayRunning(self.holidayId):
            self.request('BattleCheer')
        else:
            self.notify.debug('not going to battleCheer because holiday %d is not running' % self.holidayId)

    def gotoIdle(self):
        self.notify.debugStateCall(self)
        if base.cr.newsManager.isHolidayRunning(self.holidayId):
            self.request('DoIdleAnim')
        else:
            self.notify.debug('not going to idle because holiday %d is not running' % self.holidayId)

    def gotoVictory(self):
        self.notify.debugStateCall(self)
        if base.cr.newsManager.isHolidayRunning(self.holidayId):
            self.request('Victory')
        else:
            self.notify.debug('not going to victory because holiday %d is not running' % self.holidayId)

    def gotoSad(self, buildingDoId):
        self.notify.debugStateCall(self)
        self.buildingsMakingMeSad.add(buildingDoId)
        if base.cr.newsManager.isHolidayRunning(self.holidayId):
            self.request('Sad')
        else:
            self.notify.debug('not going to sad because holiday %d is not running' % self.holidayId)

    def buildingLiberated(self, buildingDoId):
        self.buildingsMakingMeSad.discard(buildingDoId)
        if not self.buildingsMakingMeSad:
            self.gotoIdle()

    def enterFaceoff(self):
        self.notify.debugStateCall(self)
        self.curIval = self.createFaceoffInterval()
        self.curIval.start()

    def exitFaceoff(self):
        self.notify.debugStateCall(self)
        self.curIval.pause()
        self.curIval = None
        return

    def calcWhichIdleAnim(self, animName):
        result = 0
        info = self.ZoneToIdles[self.hoodId]
        for index, curInfo in enumerate(info):
            if isinstance(curInfo, tuple):
                if curInfo[0] == animName:
                    result = index
                    break
            elif isinstance(curInfo, str):
                if curInfo == animName:
                    result = index
                    breal

        return result

    def createFaceoffInterval(self):
        result = Sequence()
        if self.lastIdleAnimName:
            whichIdleAnim = self.calcWhichIdleAnim(self.lastIdleAnimName)
            animAndSound = self.createIdleAnimAndSoundInterval(whichIdleAnim, self.lastIdleTime)
            result.append(animAndSound)
        idleIntoFightIval = self.createAnimAndSoundIval('idleIntoFight')
        result.append(idleIntoFightIval)
        result.append(Func(self.gotoBattleCheer))
        return result

    def enterBattleCheer(self):
        self.notify.debugStateCall(self)
        self.curIval = self.battleCheerInterval
        if self.curIval:
            self.curIval.loop()

    def exitBattleCheer(self):
        self.notify.debugStateCall(self)
        if self.curIval:
            self.curIval.finish()
            self.curIval = None
        return

    def enterVictory(self):
        self.notify.debugStateCall(self)
        self.curIval = self.victoryInterval
        if self.curIval:
            self.curIval.loop()

    def exitVictory(self):
        self.notify.debugStateCall(self)
        if self.curIval:
            self.curIval.finish()
            self.curIval = None
        return

    def enterSad(self):
        self.notify.debugStateCall(self)
        self.curIval = self.sadInterval
        if self.curIval:
            self.curIval.loop()

    def exitSad(self):
        self.notify.debugStateCall(self)
        if self.curIval:
            self.curIval.finish()
            self.curIval = None
        return

    def getSettleName(self, whichIdleAnim):
        result = None
        if isinstance(self.ZoneToIdles[self.hoodId][whichIdleAnim], tuple) and len(self.ZoneToIdles[self.hoodId][whichIdleAnim]) > 3:
            result = self.ZoneToIdles[self.hoodId][whichIdleAnim][3]
        return result

    def getOrigIdleAnimName(self, whichIdleAnim):
        result = None
        if isinstance(self.ZoneToIdles[self.hoodId][whichIdleAnim], tuple):
            result = self.ZoneToIdles[self.hoodId][whichIdleAnim][0]
        else:
            result = self.ZoneToIdles[self.hoodId][whichIdleAnim]
        return result

    def createAnimAndSoundIval(self, animKey):
        animIval = self.node.actorInterval(animKey)
        animIvalDuration = animIval.getDuration()
        origAnimName = self.node.getAnimFilename(animKey)
        soundIval = self.createSoundInterval(origAnimName, animIvalDuration)
        soundIvalDuration = soundIval.getDuration()
        printFunc = Func(self.printAnimIfClose, animKey)
        if self.hasSpecialIval(origAnimName):
            specialIval = self.getSpecialIval(origAnimName)
            idleAnimAndSound = Parallel(animIval, soundIval, specialIval)
            if base.config.GetBool('interactive-prop-info', False):
                idleAnimAndSound.append(printFunc)
        else:
            idleAnimAndSound = Parallel(animIval, soundIval)
            if base.config.GetBool('interactive-prop-info', False):
                idleAnimAndSound.append(printFunc)
        return idleAnimAndSound

    def printAnimIfClose(self, animKey):
        if base.config.GetBool('interactive-prop-info', False):
            try:
                animName = self.node.getAnimFilename(animKey)
                baseAnimName = animName.split('/')[-1]
                if localAvatar.zoneId == self.visId:
                    self.notify.info('playing %s' % baseAnimName)
            except Exception as e:
                self.notify.warning('Unknown error in printAnimIfClose, giving up:\n%s' % str(e))

    def clearCurIval(self):
        if self.curIval:
            self.curIval.finish()
        clearPythonIvals(self.curIval)
        self.curIval = None
        return
Beispiel #52
0
class Text(Entity):

    size = .025
    default_font = 'OpenSans-Regular.ttf'
    default_resolution = 1080 * size * 2
    start_tag = '<'
    end_tag = '>'

    def __init__(self,
                 text='',
                 start_tag=start_tag,
                 end_tag=end_tag,
                 ignore=True,
                 **kwargs):
        super().__init__(ignore=ignore)
        self.size = Text.size
        self.parent = camera.ui

        self.setColorScaleOff()
        self.text_nodes = list()
        self.images = list()
        self.origin = (-.5, .5)

        self.font = Text.default_font
        self.resolution = Text.default_resolution
        self.line_height = 1
        self.use_tags = True
        self.start_tag = start_tag
        self.end_tag = end_tag
        self.text_colors = {'default': color.text_color}

        for color_name in color.color_names:
            self.text_colors[color_name] = color.colors[color_name]

        self.tag = Text.start_tag + 'default' + Text.end_tag
        self.current_color = self.text_colors['default']
        self.scale_override = 1
        self._background = None
        self.appear_sequence = None  # gets created when calling appear()

        if text != '':
            self.text = text

        for key, value in kwargs.items():
            setattr(self, key, value)

    @property
    def text(self):  # set this to update the text.
        t = ''
        y = 0
        if self.text_nodes:
            # y = self.text_nodes[0].getZ()
            y = self.text_nodes[0].getY()

        for tn in self.text_nodes:
            # if y != tn.getZ():
            if y != tn.getY():
                t += '\n'
                # y = tn.getZ()
                y = tn.getY()

            t += tn.node().text

        return t

    @text.setter
    def text(self, text):
        self.raw_text = text

        # clear stuff
        for img in self.images:
            destroy(img)
        self.images.clear()

        for tn in self.text_nodes:
            tn.remove_node()
        self.text_nodes.clear()

        # check if using tags
        if (not self.use_tags or self.text == self.start_tag
                or self.text == self.end_tag or not self.start_tag in text
                or not self.end_tag in text):

            self.create_text_section(text)
            self.align()
            return

        # parse tags
        text = self.start_tag + self.end_tag + str(
            text)  # start with empty tag for alignemnt to work?
        sections = list()
        section = ''
        tag = self.start_tag + 'default' + self.end_tag
        temp_text_node = TextNode('temp_text_node')
        temp_text_node.setFont(self.font)
        x = 0
        y = 0

        i = 0
        while i < len(text):
            char = text[i]
            if char == '\n':
                sections.append([section, tag, x, y])
                section = ''
                y -= 1
                x = 0
                i += 1

            elif char == self.start_tag:  # find tag
                sections.append([section, tag, x, y])
                x += temp_text_node.calcWidth(section)
                section = ''

                tag = ''
                for j in range(len(text) - i):
                    tag += text[i + j]
                    if text[i + j] == self.end_tag and len(tag) > 0:
                        i += j + 1
                        break
            else:
                section += char
                i += 1

        sections.append([section, tag, x, y])

        for i, s in enumerate(sections):
            tag = s[1]
            # move the text after image one space right
            if tag.startswith(self.start_tag + 'image:'):
                for f in sections:
                    if f[3] == s[3] and f[2] > s[2]:
                        f[2] += .5

                s[2] += .5

            self.create_text_section(text=s[0], tag=s[1], x=s[2], y=s[3])

        self.align()

    def create_text_section(self, text, tag='', x=0, y=0):
        # print(text, tag)
        self.text_node = TextNode('t')
        self.text_node_path = self.attachNewNode(self.text_node)
        try:
            self.text_node.setFont(self._font)
        except:
            pass  # default font

        if tag != '<>':
            tag = tag[1:-1]

            if tag.startswith('hsb('):  # set color based on numbers
                tag = tag[4:-1]
                hsb_values = tuple(float(e.strip()) for e in tag.split(','))
                self.current_color = color.color(*hsb_values)

            elif tag.startswith('rgb('):  # set color based on numbers
                tag = tag[4:-1]
                rgb_values = (float(e.strip()) for e in tag.split(','))
                self.current_color = color.rgba(*rgb_values)

            if tag.startswith('scale:'):
                scale = tag.split(':')[1]
                self.scale_override = float(scale)

            elif tag.startswith('image:'):
                texture_name = tag.split(':')[1]
                image = Entity(
                    parent=self.text_node_path,
                    name='inline_image',
                    model='quad',
                    texture=texture_name,
                    color=self.current_color,
                    scale=1,
                    # position=(x*self.size*self.scale_override, y*self.size*self.line_height),
                    origin=(.0, -.25),
                    add_to_scene_entities=False,
                )
                if not image.texture:
                    destroy(image)
                else:
                    self.images.append(image)
                    # self.text_node.remove_node()
                    # self.text_node = image
            else:
                if tag in self.text_colors:
                    self.current_color = self.text_colors[tag]

        self.text_node_path.setScale(self.scale_override * self.size)
        self.text_node.setText(text)
        self.text_node.setTextColor(self.current_color)
        self.text_node.setPreserveTrailingWhitespace(True)
        # self.text_node_path.setPos(
        #     x * self.size * self.scale_override,
        #     0,
        #     (y * self.size * self.line_height) - .75 * self.size)
        self.text_node_path.setPos(x * self.size * self.scale_override,
                                   (y * self.size * self.line_height) -
                                   .75 * self.size, 0)
        self.text_nodes.append(self.text_node_path)

        return self.text_node

    @property
    def font(self):
        return self._font

    @font.setter
    def font(self, value):
        font = loader.loadFont(value)
        if font:
            self._font = font
            self._font.clear()  # remove assertion warning
            self._font.setPixelsPerUnit(self.resolution)
            self.text = self.raw_text  # update tex

    @property
    def color(self):  # sets the default color.
        return self._color

    @color.setter
    def color(self, value):
        self._color = value
        self.current_color = value
        self.text_colors['default'] = value
        for tn in self.text_nodes:
            tn.node().setTextColor(value)

    @property
    def line_height(self):
        try:
            return self._line_height
        except:
            return 1

    @line_height.setter
    def line_height(self, value):
        self._line_height = value
        self.text = self.raw_text

    @property
    def width(self):  # gets the width of the widest line.
        if not hasattr(self, 'text'):
            return 0

        temp_text_node = TextNode('temp')
        temp_text_node.setFont(self._font)

        longest_line_length = 0
        for line in self.text.split('\n'):
            longest_line_length = max(longest_line_length,
                                      temp_text_node.calcWidth(line))

        return longest_line_length * self.scale_x * self.size

    @property
    def height(self):  # gets the height of the text
        return (len(self.lines) * self.line_height * self.scale_y * self.size)

    @property
    def lines(self):
        return self.text.splitlines()

    @property
    def resolution(self):
        return self._font.getPixelsPerUnit()

    @resolution.setter
    def resolution(self, value):
        self._font.setPixelsPerUnit(value)

    @property
    def wordwrap(
        self
    ):  # set this to make the text wrap after a certain number of characters.
        if hasattr(self, '_wordwrap'):
            return self._wordwrap
        else:
            return 0

    @wordwrap.setter
    def wordwrap(self, value):
        self._wordwrap = value
        new_text = ''
        is_in_tag = False
        i = 0
        for word in self.raw_text.replace('\n', ' ').replace(
                self.end_tag, self.end_tag + ' ').split(' '):

            if word.startswith(self.start_tag) and new_text:
                new_text = new_text[:-1]

            if not word.startswith(self.start_tag):
                i += len(word)

            if i >= value:
                new_text += '\n'
                i = 0

            new_text += word + ' '

        # print('--------------------\n', new_text)
        self.text = new_text

    @property
    def origin(self):
        return self._origin

    @origin.setter
    def origin(self, value):
        self._origin = value
        if self.text:
            self.text = self.raw_text

    @property
    def background(self):
        return self._background

    @background.setter
    def background(self, value):
        if value == True:
            self.create_background()
        elif self._background:
            destroy(self._background)

    def align(self):
        value = self.origin
        linewidths = [
            self.text_nodes[0].node().calcWidth(line) for line in self.lines
        ]
        # print('.........', linewidths)
        for tn in self.text_nodes:
            # center text horizontally
            # linenumber = abs(int(tn.getZ() / self.size / self.line_height))
            linenumber = abs(int(tn.getY() / self.size / self.line_height))
            tn.setX(tn.getX() - (linewidths[linenumber] / 2 * self.size *
                                 tn.getScale()[0] / self.size))
            # tn.setX(tn.getX() - (linewidths[linenumber] / 2 * self.size))
            # add offset based on origin/value
            # x -= half line width * text node scale
            tn.setX(tn.getX() -
                    (linewidths[linenumber] / 2 * value[0] * 2 * self.size) *
                    tn.getScale()[0] / self.size)
            # center text vertically
            halfheight = len(linewidths) * self.line_height / 2
            # tn.setZ(tn.getZ() + (halfheight * self.size))
            tn.setY(tn.getY() + (halfheight * self.size))
            # add offset
            # tn.setZ(tn.getZ() - (halfheight * value[1] * 2 * self.size))
            tn.setY(tn.getY() - (halfheight * value[1] * 2 * self.size))

    def create_background(self,
                          padding=size * 2,
                          radius=size,
                          color=ursina.color.black66):
        from ursina import Quad, destroy

        if self._background:
            destroy(self._background)

        self._background = Entity(parent=self, z=.01)

        if isinstance(padding, (int, float, complex)):
            padding = (padding, padding)

        w, h = self.width + padding[0], self.height + padding[1]
        self._background.x -= self.origin_x * self.width
        self._background.y -= self.origin_y * self.height

        self._background.model = Quad(radius=radius,
                                      scale=(w / self.scale_x,
                                             h / self.scale_y))
        self._background.color = color

    def appear(self, speed=.025, delay=0):
        from ursina.ursinastuff import invoke
        self.enabled = True
        # self.visible = True   # setting visible seems to reset the colors
        if self.appear_sequence:
            self.appear_sequence.finish()

        x = 0
        self.appear_sequence = Sequence()
        for i, tn in enumerate(self.text_nodes):
            target_text = tn.node().getText()
            tn.node().setText('')
            new_text = ''

            for j, char in enumerate(target_text):
                new_text += char
                self.appear_sequence.append(Wait(speed))
                self.appear_sequence.append(Func(tn.node().setText, new_text))

        self.appear_sequence.start()
        return self.appear_sequence

    def get_width(string, font=None):
        t = Text(string)
        if font:
            t.font = font
        w = t.width
        from ursina import destroy
        destroy(t)
        return w
Beispiel #53
0
class DistributedPartyCatchActivity(DistributedPartyActivity,
                                    DistributedPartyCatchActivityBase):
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'DistributedPartyCatchActivity')
    DropTaskName = 'dropSomething'
    DropObjectPlurals = {
        'apple': TTLocalizer.PartyCatchActivityApples,
        'orange': TTLocalizer.PartyCatchActivityOranges,
        'pear': TTLocalizer.PartyCatchActivityPears,
        'coconut': TTLocalizer.PartyCatchActivityCoconuts,
        'watermelon': TTLocalizer.PartyCatchActivityWatermelons,
        'pineapple': TTLocalizer.PartyCatchActivityPineapples,
        'anvil': TTLocalizer.PartyCatchActivityAnvils
    }

    class Generation:
        def __init__(self, generation, startTime, startNetworkTime,
                     numPlayers):
            self.generation = generation
            self.startTime = startTime
            self.startNetworkTime = startNetworkTime
            self.numPlayers = numPlayers
            self.hasBeenScheduled = False
            self.droppedObjNames = []
            self.dropSchedule = []
            self.numItemsDropped = 0
            self.droppedObjCaught = {}

    def __init__(self, cr):
        DistributedPartyActivity.__init__(
            self,
            cr,
            PartyGlobals.ActivityIds.PartyCatch,
            PartyGlobals.ActivityTypes.HostInitiated,
            wantRewardGui=True)
        self.setUsesSmoothing()
        self.setUsesLookAround()
        self._sNumGen = SerialNumGen()

    def getTitle(self):
        return TTLocalizer.PartyCatchActivityTitle

    def getInstructions(self):
        return TTLocalizer.PartyCatchActivityInstructions % {
            'badThing': self.DropObjectPlurals['anvil']
        }

    def generate(self):
        DistributedPartyActivity.generate(self)
        self.notify.info('localAvatar doId: %s' % base.localAvatar.doId)
        self.notify.info('generate()')
        self._generateFrame = globalClock.getFrameCount()
        self._id2gen = {}
        self._orderedGenerations = []
        self._orderedGenerationIndex = None
        rng = RandomNumGen(self.doId)
        self._generationSeedBase = rng.randrange(1000)
        self._lastDropTime = 0.0
        return

    def getCurGeneration(self):
        if self._orderedGenerationIndex is None:
            return
        return self._orderedGenerations[self._orderedGenerationIndex]

    def _addGeneration(self, generation, startTime, startNetworkTime,
                       numPlayers):
        self._id2gen[generation] = self.Generation(generation, startTime,
                                                   startNetworkTime,
                                                   numPlayers)
        i = 0
        while 1:
            if i >= len(self._orderedGenerations):
                break
            gen = self._orderedGenerations[i]
            startNetT = self._id2gen[gen].startTime
            genId = self._id2gen[gen].generation
            if startNetT > startNetworkTime:
                break
            if startNetT == startNetworkTime and genId > generation:
                break
            i += 1

        self._orderedGenerations = self._orderedGenerations[:i] + [
            generation
        ] + self._orderedGenerations[i:]
        if self._orderedGenerationIndex is not None:
            if self._orderedGenerationIndex >= i:
                self._orderedGenerationIndex += 1
        return

    def _removeGeneration(self, generation):
        del self._id2gen[generation]
        i = self._orderedGenerations.index(generation)
        self._orderedGenerations = self._orderedGenerations[:
                                                            i] + self._orderedGenerations[
                                                                i + 1:]
        if self._orderedGenerationIndex is not None:
            if len(self._orderedGenerations):
                if self._orderedGenerationIndex >= i:
                    self._orderedGenerationIndex -= 1
            else:
                self._orderedGenerationIndex = None
        return

    def announceGenerate(self):
        self.notify.info('announceGenerate()')
        self.catchTreeZoneEvent = 'fence_floor'
        DistributedPartyActivity.announceGenerate(self)

    def load(self, loadModels=1, arenaModel='partyCatchTree'):
        self.notify.info('load()')
        DistributedPartyCatchActivity.notify.debug('PartyCatch: load')
        self.activityFSM = CatchActivityFSM(self)
        if __dev__:
            for o in xrange(3):
                print {
                    0: 'SPOTS PER PLAYER',
                    1: 'DROPS PER MINUTE PER SPOT DURING NORMAL DROP PERIOD',
                    2: 'DROPS PER MINUTE PER PLAYER DURING NORMAL DROP PERIOD'
                }[o]
                for i in xrange(1, self.FallRateCap_Players + 10):
                    self.defineConstants(forceNumPlayers=i)
                    numDropLocations = self.DropRows * self.DropColumns
                    numDropsPerMin = 60.0 / self.DropPeriod
                    if o == 0:
                        spotsPerPlayer = numDropLocations / float(i)
                        print '%2d PLAYERS: %s' % (i, spotsPerPlayer)
                    elif o == 1:
                        numDropsPerMinPerSpot = numDropsPerMin / numDropLocations
                        print '%2d PLAYERS: %s' % (i, numDropsPerMinPerSpot)
                    elif i > 0:
                        numDropsPerMinPerPlayer = numDropsPerMin / i
                        print '%2d PLAYERS: %s' % (i, numDropsPerMinPerPlayer)

        self.defineConstants()
        self.treesAndFence = loader.loadModel('phase_13/models/parties/%s' %
                                              arenaModel)
        self.treesAndFence.setScale(0.9)
        self.treesAndFence.find('**/fence_floor').setPos(0.0, 0.0, 0.1)
        self.treesAndFence.reparentTo(self.root)
        ground = self.treesAndFence.find('**/groundPlane')
        ground.setBin('ground', 1)
        DistributedPartyActivity.load(self)
        exitText = TextNode('PartyCatchExitText')
        exitText.setCardAsMargin(0.1, 0.1, 0.1, 0.1)
        exitText.setCardDecal(True)
        exitText.setCardColor(1.0, 1.0, 1.0, 0.0)
        exitText.setText(TTLocalizer.PartyCatchActivityExit)
        exitText.setTextColor(0.0, 8.0, 0.0, 0.9)
        exitText.setAlign(exitText.ACenter)
        exitText.setFont(ToontownGlobals.getBuildingNametagFont())
        exitText.setShadowColor(0, 0, 0, 1)
        exitText.setBin('fixed')
        if TTLocalizer.BuildingNametagShadow:
            exitText.setShadow(*TTLocalizer.BuildingNametagShadow)
        exitTextLoc = self.treesAndFence.find('**/loc_exitSignText')
        exitTextNp = exitTextLoc.attachNewNode(exitText)
        exitTextNp.setDepthWrite(0)
        exitTextNp.setScale(4)
        exitTextNp.setZ(-0.5)
        self.sign.reparentTo(self.treesAndFence.find('**/loc_eventSign'))
        self.sign.wrtReparentTo(self.root)
        self.avatarNodePath = NodePath('PartyCatchAvatarNodePath')
        self.avatarNodePath.reparentTo(self.root)
        self._avatarNodePathParentToken = 3
        base.cr.parentMgr.registerParent(self._avatarNodePathParentToken,
                                         self.avatarNodePath)
        self.toonSDs = {}
        self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow')
        self.dropObjModels = {}
        if loadModels:
            self.__loadDropModels()
        self.sndGoodCatch = base.loader.loadSfx(
            'phase_4/audio/sfx/SZ_DD_treasure.ogg')
        self.sndOof = base.loader.loadSfx(
            'phase_4/audio/sfx/MG_cannon_hit_dirt.ogg')
        self.sndAnvilLand = base.loader.loadSfx(
            'phase_4/audio/sfx/AA_drop_anvil_miss.ogg')
        self.sndPerfect = base.loader.loadSfx(
            'phase_4/audio/sfx/ring_perfect.ogg')
        self.__textGen = TextNode('partyCatchActivity')
        self.__textGen.setFont(ToontownGlobals.getSignFont())
        self.__textGen.setAlign(TextNode.ACenter)
        self.activityFSM.request('Idle')

    def __loadDropModels(self):
        for objType in PartyGlobals.DropObjectTypes:
            model = loader.loadModel(objType.modelPath)
            self.dropObjModels[objType.name] = model
            modelScales = {
                'apple': 0.7,
                'orange': 0.7,
                'pear': 0.5,
                'coconut': 0.7,
                'watermelon': 0.6,
                'pineapple': 0.45
            }
            if modelScales.has_key(objType.name):
                model.setScale(modelScales[objType.name])
            if objType == PartyGlobals.Name2DropObjectType['pear']:
                model.setZ(-0.6)
            if objType == PartyGlobals.Name2DropObjectType['coconut']:
                model.setP(180)
            if objType == PartyGlobals.Name2DropObjectType['watermelon']:
                model.setH(135)
                model.setZ(-0.5)
            if objType == PartyGlobals.Name2DropObjectType['pineapple']:
                model.setZ(-1.7)
            if objType == PartyGlobals.Name2DropObjectType['anvil']:
                model.setZ(-self.ObjRadius)
            model.flattenStrong()

    def unload(self):
        DistributedPartyCatchActivity.notify.debug('unload')
        self.finishAllDropIntervals()
        self.destroyOrthoWalk()
        DistributedPartyActivity.unload(self)
        self.stopDropTask()
        del self.activityFSM
        del self.__textGen
        for avId in self.toonSDs.keys():
            if self.toonSDs.has_key(avId):
                toonSD = self.toonSDs[avId]
                toonSD.unload()

        del self.toonSDs
        self.treesAndFence.removeNode()
        del self.treesAndFence
        self.dropShadow.removeNode()
        del self.dropShadow
        base.cr.parentMgr.unregisterParent(self._avatarNodePathParentToken)
        for model in self.dropObjModels.values():
            model.removeNode()

        del self.dropObjModels
        del self.sndGoodCatch
        del self.sndOof
        del self.sndAnvilLand
        del self.sndPerfect

    def setStartTimestamp(self, timestamp32):
        self.notify.info('setStartTimestamp(%s)' % (timestamp32, ))
        self._startTimestamp = globalClockDelta.networkToLocalTime(timestamp32,
                                                                   bits=32)

    def getCurrentCatchActivityTime(self):
        return globalClock.getFrameTime() - self._startTimestamp

    def getObjModel(self, objName):
        return self.dropObjModels[objName].copyTo(hidden)

    def joinRequestDenied(self, reason):
        DistributedPartyActivity.joinRequestDenied(self, reason)
        base.cr.playGame.getPlace().fsm.request('walk')

    def handleToonJoined(self, toonId):
        if not self.toonSDs.has_key(toonId):
            toonSD = PartyCatchActivityToonSD(toonId, self)
            self.toonSDs[toonId] = toonSD
            toonSD.load()
        self.notify.debug('handleToonJoined : currentState = %s' %
                          self.activityFSM.state)
        if config.GetBool('always-max-lod', False):
            self.cr.doId2do[toonId].useLOD(1000)
        else:
            self.cr.doId2do[toonId].useLOD(500)
        if self.activityFSM.state == 'Active':
            if self.toonSDs.has_key(toonId):
                self.toonSDs[toonId].enter()
            if base.localAvatar.doId == toonId:
                base.localAvatar.b_setParent(self._avatarNodePathParentToken)
                self.putLocalAvatarInActivity()
            if self.toonSDs.has_key(toonId):
                self.toonSDs[toonId].fsm.request('rules')

    def handleToonExited(self, toonId):
        self.notify.debug('handleToonExited( toonId=%s )' % toonId)
        if self.cr.doId2do.has_key(toonId):
            self.cr.doId2do[toonId].resetLOD()
            if self.toonSDs.has_key(toonId):
                self.toonSDs[toonId].fsm.request('notPlaying')
                self.toonSDs[toonId].exit()
                self.toonSDs[toonId].unload()
                del self.toonSDs[toonId]
            if base.localAvatar.doId == toonId:
                base.localAvatar.b_setParent(ToontownGlobals.SPRender)

    def takeLocalAvatarOutOfActivity(self):
        self.notify.debug('localToon has left the circle')
        camera.reparentTo(base.localAvatar)
        base.localAvatar.startUpdateSmartCamera()
        base.localAvatar.enableSmartCameraViews()
        base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex)
        DistributedSmoothNode.activateSmoothing(1, 0)

    def _enableCollisions(self):
        DistributedPartyActivity._enableCollisions(self)
        self._enteredTree = False
        self.accept('enter' + self.catchTreeZoneEvent,
                    self._toonMayHaveEnteredTree)
        self.accept('again' + self.catchTreeZoneEvent,
                    self._toonMayHaveEnteredTree)
        self.accept('exit' + self.catchTreeZoneEvent, self._toonExitedTree)
        self.accept(DistributedPartyCannonActivity.LOCAL_TOON_LANDED_EVENT,
                    self._handleCannonLanded)

    def _disableCollisions(self):
        self.ignore(DistributedPartyCannonActivity.LOCAL_TOON_LANDED_EVENT)
        self.ignore('enter' + self.catchTreeZoneEvent)
        self.ignore('again' + self.catchTreeZoneEvent)
        self.ignore('exit' + self.catchTreeZoneEvent)
        DistributedPartyActivity._disableCollisions(self)

    def _handleCannonLanded(self):
        x = base.localAvatar.getX()
        y = base.localAvatar.getY()
        if x > self.x - self.StageHalfWidth and x < self.x + self.StageHalfWidth and y > self.y - self.StageHalfHeight and y < self.y + self.StageHalfHeight:
            self._toonEnteredTree(None)
        return

    def _toonMayHaveEnteredTree(self, collEntry):
        if self._enteredTree:
            return
        if base.localAvatar.controlManager.currentControls.getIsAirborne():
            return
        self._toonEnteredTree(collEntry)

    def _toonEnteredTree(self, collEntry):
        self.notify.debug('_toonEnteredTree : avid = %s' %
                          base.localAvatar.doId)
        self.notify.debug('_toonEnteredTree : currentState = %s' %
                          self.activityFSM.state)
        if self.isLocalToonInActivity():
            return
        if self.activityFSM.state == 'Active':
            base.cr.playGame.getPlace().fsm.request('activity')
            self.d_toonJoinRequest()
        else:
            if self.activityFSM.state == 'Idle':
                base.cr.playGame.getPlace().fsm.request('activity')
                self.d_toonJoinRequest()
        self._enteredTree = True

    def _toonExitedTree(self, collEntry):
        self.notify.debug('_toonExitedTree : avid = %s' %
                          base.localAvatar.doId)
        self._enteredTree = False
        if hasattr(
                base.cr.playGame.getPlace(), 'fsm'
        ) and self.activityFSM.state == 'Active' and self.isLocalToonInActivity(
        ):
            if self.toonSDs.has_key(base.localAvatar.doId):
                self.takeLocalAvatarOutOfActivity()
                self.toonSDs[base.localAvatar.doId].fsm.request('notPlaying')
            self.d_toonExitDemand()

    def setToonsPlaying(self, toonIds):
        self.notify.info('setToonsPlaying(%s)' % (toonIds, ))
        DistributedPartyActivity.setToonsPlaying(self, toonIds)
        if self.isLocalToonInActivity(
        ) and base.localAvatar.doId not in toonIds:
            if self.toonSDs.has_key(base.localAvatar.doId):
                self.takeLocalAvatarOutOfActivity()
                self.toonSDs[base.localAvatar.doId].fsm.request('notPlaying')

    def __genText(self, text):
        self.__textGen.setText(text)
        return self.__textGen.generate()

    def getNumPlayers(self):
        return len(self.toonIds)

    def defineConstants(self, forceNumPlayers=None):
        DistributedPartyCatchActivity.notify.debug('defineConstants')
        self.ShowObjSpheres = 0
        self.ShowToonSpheres = 0
        self.useGravity = True
        self.trickShadows = True
        if forceNumPlayers is None:
            numPlayers = self.getNumPlayers()
        else:
            numPlayers = forceNumPlayers
        self.calcDifficultyConstants(numPlayers)
        DistributedPartyCatchActivity.notify.debug('ToonSpeed: %s' %
                                                   self.ToonSpeed)
        DistributedPartyCatchActivity.notify.debug('total drops: %s' %
                                                   self.totalDrops)
        DistributedPartyCatchActivity.notify.debug('numFruits: %s' %
                                                   self.numFruits)
        DistributedPartyCatchActivity.notify.debug('numAnvils: %s' %
                                                   self.numAnvils)
        self.ObjRadius = 1.0
        dropRegionTable = PartyRegionDropPlacer.getDropRegionTable(numPlayers)
        self.DropRows, self.DropColumns = len(dropRegionTable), len(
            dropRegionTable[0])
        for objType in PartyGlobals.DropObjectTypes:
            DistributedPartyCatchActivity.notify.debug('*** Object Type: %s' %
                                                       objType.name)
            objType.onscreenDuration = objType.onscreenDurMult * self.BaselineOnscreenDropDuration
            DistributedPartyCatchActivity.notify.debug(
                'onscreenDuration=%s' % objType.onscreenDuration)
            v_0 = 0.0
            t = objType.onscreenDuration
            x_0 = self.MinOffscreenHeight
            x = 0.0
            g = 2.0 * (x - x_0 - v_0 * t) / (t * t)
            DistributedPartyCatchActivity.notify.debug('gravity=%s' % g)
            objType.trajectory = Trajectory(0,
                                            Vec3(0, 0, x_0),
                                            Vec3(0, 0, v_0),
                                            gravMult=abs(g /
                                                         Trajectory.gravity))
            objType.fallDuration = objType.onscreenDuration + self.OffscreenTime

        return

    def grid2world(self, column, row):
        x = column / float(self.DropColumns - 1)
        y = row / float(self.DropRows - 1)
        x = x * 2.0 - 1.0
        y = y * 2.0 - 1.0
        x *= self.StageHalfWidth
        y *= self.StageHalfHeight
        return (x, y)

    def showPosts(self):
        self.hidePosts()
        self.posts = [Toon.Toon(), Toon.Toon(), Toon.Toon(), Toon.Toon()]
        for i in range(len(self.posts)):
            tree = self.posts[i]
            tree.reparentTo(render)
            x = self.StageHalfWidth
            y = self.StageHalfHeight
            if i > 1:
                x = -x
            if i % 2:
                y = -y
            tree.setPos(x + self.x, y + self.y, 0)

    def hidePosts(self):
        if hasattr(self, 'posts'):
            for tree in self.posts:
                tree.removeNode()

            del self.posts

    def showDropGrid(self):
        self.hideDropGrid()
        self.dropMarkers = []
        for row in range(self.DropRows):
            self.dropMarkers.append([])
            rowList = self.dropMarkers[row]
            for column in range(self.DropColumns):
                toon = Toon.Toon()
                toon.setDNA(base.localAvatar.getStyle())
                toon.reparentTo(self.root)
                toon.setScale(1.0 / 3)
                x, y = self.grid2world(column, row)
                toon.setPos(x, y, 0)
                rowList.append(toon)

    def hideDropGrid(self):
        if hasattr(self, 'dropMarkers'):
            for row in self.dropMarkers:
                for marker in row:
                    marker.removeNode()

            del self.dropMarkers

    def handleToonDisabled(self, avId):
        DistributedPartyCatchActivity.notify.debug('handleToonDisabled')
        DistributedPartyCatchActivity.notify.debug('avatar ' + str(avId) +
                                                   ' disabled')
        if self.toonSDs.has_key(avId):
            self.toonSDs[avId].exit(unexpectedExit=True)
        del self.toonSDs[avId]

    def turnOffSmoothingOnGuests(self):
        pass

    def setState(self, newState, timestamp):
        self.notify.info('setState(%s, %s)' % (newState, timestamp))
        DistributedPartyCatchActivity.notify.debug(
            'setState( newState=%s, ... )' % newState)
        DistributedPartyActivity.setState(self, newState, timestamp)
        self.activityFSM.request(newState)
        if newState == 'Active':
            if base.localAvatar.doId != self.party.partyInfo.hostId:
                if globalClock.getFrameCount() > self._generateFrame:
                    if base.localAvatar.getX(
                    ) > self.x - self.StageHalfWidth and base.localAvatar.getX(
                    ) < self.x + self.StageHalfWidth and base.localAvatar.getY(
                    ) > self.y - self.StageHalfHeight and base.localAvatar.getY(
                    ) < self.y + self.StageHalfHeight:
                        self._toonEnteredTree(None)
        return

    def putLocalAvatarInActivity(self):
        if base.cr.playGame.getPlace() and hasattr(base.cr.playGame.getPlace(),
                                                   'fsm'):
            base.cr.playGame.getPlace().fsm.request('activity', [False])
        else:
            self.notify.info(
                "Avoided crash: toontown.parties.DistributedPartyCatchActivity:632, toontown.parties.DistributedPartyCatchActivity:1198, toontown.parties.activityFSMMixins:49, direct.fsm.FSM:423, AttributeError: 'NoneType' object has no attribute 'fsm'"
            )
        base.localAvatar.stopUpdateSmartCamera()
        camera.reparentTo(self.treesAndFence)
        camera.setPosHpr(0.0, -63.0, 30.0, 0.0, -20.0, 0.0)
        if not hasattr(self, 'ltLegsCollNode'):
            self.createCatchCollisions()

    def createCatchCollisions(self):
        radius = 0.7
        handler = CollisionHandlerEvent()
        handler.setInPattern('ltCatch%in')
        self.ltLegsCollNode = CollisionNode('catchLegsCollNode')
        self.ltLegsCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask)
        self.ltHeadCollNode = CollisionNode('catchHeadCollNode')
        self.ltHeadCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask)
        self.ltLHandCollNode = CollisionNode('catchLHandCollNode')
        self.ltLHandCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask)
        self.ltRHandCollNode = CollisionNode('catchRHandCollNode')
        self.ltRHandCollNode.setCollideMask(PartyGlobals.CatchActivityBitmask)
        legsCollNodepath = base.localAvatar.attachNewNode(self.ltLegsCollNode)
        legsCollNodepath.hide()
        head = base.localAvatar.getHeadParts().getPath(2)
        headCollNodepath = head.attachNewNode(self.ltHeadCollNode)
        headCollNodepath.hide()
        lHand = base.localAvatar.getLeftHands()[0]
        lHandCollNodepath = lHand.attachNewNode(self.ltLHandCollNode)
        lHandCollNodepath.hide()
        rHand = base.localAvatar.getRightHands()[0]
        rHandCollNodepath = rHand.attachNewNode(self.ltRHandCollNode)
        rHandCollNodepath.hide()
        base.localAvatar.cTrav.addCollider(legsCollNodepath, handler)
        base.localAvatar.cTrav.addCollider(headCollNodepath, handler)
        base.localAvatar.cTrav.addCollider(lHandCollNodepath, handler)
        base.localAvatar.cTrav.addCollider(lHandCollNodepath, handler)
        if self.ShowToonSpheres:
            legsCollNodepath.show()
            headCollNodepath.show()
            lHandCollNodepath.show()
            rHandCollNodepath.show()
        self.ltLegsCollNode.addSolid(CollisionSphere(0, 0, radius, radius))
        self.ltHeadCollNode.addSolid(CollisionSphere(0, 0, 0, radius))
        self.ltLHandCollNode.addSolid(
            CollisionSphere(0, 0, 0, 2 * radius / 3.0))
        self.ltRHandCollNode.addSolid(
            CollisionSphere(0, 0, 0, 2 * radius / 3.0))
        self.toonCollNodes = [
            legsCollNodepath, headCollNodepath, lHandCollNodepath,
            rHandCollNodepath
        ]

    def destroyCatchCollisions(self):
        if not hasattr(self, 'ltLegsCollNode'):
            return
        for collNode in self.toonCollNodes:
            while collNode.node().getNumSolids():
                collNode.node().removeSolid(0)

            base.localAvatar.cTrav.removeCollider(collNode)

        del self.toonCollNodes
        del self.ltLegsCollNode
        del self.ltHeadCollNode
        del self.ltLHandCollNode
        del self.ltRHandCollNode

    def timerExpired(self):
        pass

    def __handleCatch(self, generation, objNum):
        DistributedPartyCatchActivity.notify.debug('catch: %s' %
                                                   [generation, objNum])
        if base.localAvatar.doId not in self.toonIds:
            return
        self.showCatch(base.localAvatar.doId, generation, objNum)
        objName = self._id2gen[generation].droppedObjNames[objNum]
        objTypeId = PartyGlobals.Name2DOTypeId[objName]
        self.sendUpdate('claimCatch', [generation, objNum, objTypeId])
        self.finishDropInterval(generation, objNum)

    def showCatch(self, avId, generation, objNum):
        if not self.toonSDs.has_key(avId):
            return
        isLocal = avId == base.localAvatar.doId
        if generation not in self._id2gen:
            return
        if not self._id2gen[generation].hasBeenScheduled:
            return
        objName = self._id2gen[generation].droppedObjNames[objNum]
        objType = PartyGlobals.Name2DropObjectType[objName]
        if objType.good:
            if not self._id2gen[generation].droppedObjCaught.has_key(objNum):
                if isLocal:
                    base.playSfx(self.sndGoodCatch)
                fruit = self.getObjModel(objName)
                toon = self.getAvatar(avId)
                rHand = toon.getRightHands()[1]
                self.toonSDs[avId].eatFruit(fruit, rHand)
        else:
            self.toonSDs[avId].fsm.request('fallForward')
        self._id2gen[generation].droppedObjCaught[objNum] = 1

    def setObjectCaught(self, avId, generation, objNum):
        self.notify.info('setObjectCaught(%s, %s, %s)' %
                         (avId, generation, objNum))
        if self.activityFSM.state != 'Active':
            DistributedPartyCatchActivity.notify.warning(
                'ignoring msg: object %s caught by %s' % (objNum, avId))
            return
        isLocal = avId == base.localAvatar.doId
        if not isLocal:
            DistributedPartyCatchActivity.notify.debug(
                'AI: avatar %s caught %s' % (avId, objNum))
            self.finishDropInterval(generation, objNum)
            self.showCatch(avId, generation, objNum)
        self._scheduleGenerations()
        gen = self._id2gen[generation]
        if gen.hasBeenScheduled:
            objName = gen.droppedObjNames[objNum]
            if PartyGlobals.Name2DropObjectType[objName].good:
                if hasattr(self, 'fruitsCaught'):
                    self.fruitsCaught += 1

    def finishDropInterval(self, generation, objNum):
        if hasattr(self, 'dropIntervals'):
            if self.dropIntervals.has_key((generation, objNum)):
                self.dropIntervals[(generation, objNum)].finish()

    def finishAllDropIntervals(self):
        if hasattr(self, 'dropIntervals'):
            for dropInterval in self.dropIntervals.values():
                dropInterval.finish()

    def setGenerations(self, generations):
        self.notify.info('setGenerations(%s)' % (generations, ))
        gen2t = {}
        gen2nt = {}
        gen2np = {}
        for id, timestamp32, numPlayers in generations:
            gen2t[id] = globalClockDelta.networkToLocalTime(
                timestamp32, bits=32) - self._startTimestamp
            gen2nt[id] = timestamp32
            gen2np[id] = numPlayers

        ids = self._id2gen.keys()
        for id in ids:
            if id not in gen2t:
                self._removeGeneration(id)

        for id in gen2t:
            if id not in self._id2gen:
                self._addGeneration(id, gen2t[id], gen2nt[id], gen2np[id])

    def scheduleDrops(self, genId=None):
        if genId is None:
            genId = self.getCurGeneration()
        gen = self._id2gen[genId]
        if gen.hasBeenScheduled:
            return
        fruitIndex = int((gen.startTime + 0.5 * self.DropPeriod) /
                         PartyGlobals.CatchActivityDuration)
        fruitNames = [
            'apple', 'orange', 'pear', 'coconut', 'watermelon', 'pineapple'
        ]
        fruitName = fruitNames[(fruitIndex % len(fruitNames))]
        rng = RandomNumGen(genId + self._generationSeedBase)
        gen.droppedObjNames = [fruitName
                               ] * self.numFruits + ['anvil'] * self.numAnvils
        rng.shuffle(gen.droppedObjNames)
        dropPlacer = PartyRegionDropPlacer(self,
                                           gen.numPlayers,
                                           genId,
                                           gen.droppedObjNames,
                                           startTime=gen.startTime)
        gen.numItemsDropped = 0
        tIndex = gen.startTime % PartyGlobals.CatchActivityDuration
        tPercent = float(tIndex) / PartyGlobals.CatchActivityDuration
        gen.numItemsDropped += dropPlacer.skipPercent(tPercent)
        while not dropPlacer.doneDropping(continuous=True):
            nextDrop = dropPlacer.getNextDrop()
            gen.dropSchedule.append(nextDrop)

        gen.hasBeenScheduled = True
        return

    def startDropTask(self):
        taskMgr.add(self.dropTask, self.DropTaskName)

    def stopDropTask(self):
        taskMgr.remove(self.DropTaskName)

    def _scheduleGenerations(self):
        curT = self.getCurrentCatchActivityTime()
        genIndex = self._orderedGenerationIndex
        newGenIndex = genIndex
        while genIndex is None or genIndex < len(self._orderedGenerations) - 1:
            if genIndex is None:
                nextGenIndex = 0
            else:
                nextGenIndex = genIndex + 1
            nextGenId = self._orderedGenerations[nextGenIndex]
            nextGen = self._id2gen[nextGenId]
            startT = nextGen.startTime
            if curT >= startT:
                newGenIndex = nextGenIndex
            if not nextGen.hasBeenScheduled:
                self.defineConstants(forceNumPlayers=nextGen.numPlayers)
                self.scheduleDrops(
                    genId=self._orderedGenerations[nextGenIndex])
            genIndex = nextGenIndex

        self._orderedGenerationIndex = newGenIndex
        return

    def dropTask(self, task):
        self._scheduleGenerations()
        curT = self.getCurrentCatchActivityTime()
        if self._orderedGenerationIndex is not None:
            i = self._orderedGenerationIndex
            genIndex = self._orderedGenerations[i]
            gen = self._id2gen[genIndex]
            while len(gen.dropSchedule) > 0 and gen.dropSchedule[0][0] < curT:
                drop = gen.dropSchedule[0]
                gen.dropSchedule = gen.dropSchedule[1:]
                dropTime, objName, dropCoords = drop
                objNum = gen.numItemsDropped
                x, y = self.grid2world(*dropCoords)
                dropIval = self.getDropIval(x, y, objName, genIndex, objNum)

                def cleanup(generation, objNum, self=self):
                    del self.dropIntervals[(generation, objNum)]

                dropIval.append(Func(Functor(cleanup, genIndex, objNum)))
                self.dropIntervals[(genIndex, objNum)] = dropIval
                gen.numItemsDropped += 1
                dropIval.start(curT - dropTime)
                self._lastDropTime = dropTime

        return Task.cont

    def getDropIval(self, x, y, dropObjName, generation, num):
        objType = PartyGlobals.Name2DropObjectType[dropObjName]
        id = (generation, num)
        dropNode = hidden.attachNewNode('catchDropNode%s' % (id, ))
        dropNode.setPos(x, y, 0)
        shadow = self.dropShadow.copyTo(dropNode)
        shadow.setZ(PartyGlobals.CatchDropShadowHeight)
        shadow.setColor(1, 1, 1, 1)
        object = self.getObjModel(dropObjName)
        object.reparentTo(hidden)
        if dropObjName in ('watermelon', 'anvil'):
            objH = object.getH()
            absDelta = {'watermelon': 12, 'anvil': 15}[dropObjName]
            delta = (self.randomNumGen.random() * 2.0 - 1.0) * absDelta
            newH = objH + delta
        else:
            newH = self.randomNumGen.random() * 360.0
        object.setH(newH)
        sphereName = 'FallObj%s' % (id, )
        radius = self.ObjRadius
        if objType.good:
            radius *= lerp(1.0, 1.3, 0.5)
        collSphere = CollisionSphere(0, 0, 0, radius)
        collSphere.setTangible(0)
        collNode = CollisionNode(sphereName)
        collNode.setCollideMask(PartyGlobals.CatchActivityBitmask)
        collNode.addSolid(collSphere)
        collNodePath = object.attachNewNode(collNode)
        collNodePath.hide()
        if self.ShowObjSpheres:
            collNodePath.show()
        catchEventName = 'ltCatch' + sphereName

        def eatCollEntry(forward, collEntry):
            forward()

        self.accept(
            catchEventName,
            Functor(eatCollEntry, Functor(self.__handleCatch, id[0], id[1])))

        def cleanup(self=self, dropNode=dropNode, id=id, event=catchEventName):
            self.ignore(event)
            dropNode.removeNode()

        duration = objType.fallDuration
        onscreenDuration = objType.onscreenDuration
        targetShadowScale = 0.3
        if self.trickShadows:
            intermedScale = targetShadowScale * (self.OffscreenTime /
                                                 self.BaselineDropDuration)
            shadowScaleIval = Sequence(
                LerpScaleInterval(shadow,
                                  self.OffscreenTime,
                                  intermedScale,
                                  startScale=0))
            shadowScaleIval.append(
                LerpScaleInterval(shadow,
                                  duration - self.OffscreenTime,
                                  targetShadowScale,
                                  startScale=intermedScale))
        else:
            shadowScaleIval = LerpScaleInterval(shadow,
                                                duration,
                                                targetShadowScale,
                                                startScale=0)
        targetShadowAlpha = 0.4
        shadowAlphaIval = LerpColorScaleInterval(
            shadow,
            self.OffscreenTime,
            Point4(1, 1, 1, targetShadowAlpha),
            startColorScale=Point4(1, 1, 1, 0))
        shadowIval = Parallel(shadowScaleIval, shadowAlphaIval)
        if self.useGravity:

            def setObjPos(t, objType=objType, object=object):
                z = objType.trajectory.calcZ(t)
                object.setZ(z)

            setObjPos(0)
            dropIval = LerpFunctionInterval(setObjPos,
                                            fromData=0,
                                            toData=onscreenDuration,
                                            duration=onscreenDuration)
        else:
            startPos = Point3(0, 0, self.MinOffscreenHeight)
            object.setPos(startPos)
            dropIval = LerpPosInterval(object,
                                       onscreenDuration,
                                       Point3(0, 0, 0),
                                       startPos=startPos,
                                       blendType='easeIn')
        ival = Sequence(Func(Functor(dropNode.reparentTo, self.root)),
                        Parallel(
                            Sequence(
                                WaitInterval(self.OffscreenTime),
                                Func(Functor(object.reparentTo, dropNode)),
                                dropIval), shadowIval),
                        Func(cleanup),
                        name='drop%s' % (id, ))
        if objType == PartyGlobals.Name2DropObjectType['anvil']:
            ival.append(Func(self.playAnvil))
        return ival

    def playAnvil(self):
        if base.localAvatar.doId in self.toonIds:
            base.playSfx(self.sndAnvilLand)

    def initOrthoWalk(self):
        DistributedPartyCatchActivity.notify.debug('startOrthoWalk')

        def doCollisions(oldPos, newPos, self=self):
            x = bound(newPos[0], self.StageHalfWidth, -self.StageHalfWidth)
            y = bound(newPos[1], self.StageHalfHeight, -self.StageHalfHeight)
            newPos.setX(x)
            newPos.setY(y)
            return newPos

        orthoDrive = OrthoDrive(self.ToonSpeed, instantTurn=True)
        self.orthoWalk = OrthoWalk(orthoDrive, broadcast=True)

    def destroyOrthoWalk(self):
        DistributedPartyCatchActivity.notify.debug('destroyOrthoWalk')
        if hasattr(self, 'orthoWalk'):
            self.orthoWalk.stop()
            self.orthoWalk.destroy()
            del self.orthoWalk

    def startIdle(self):
        DistributedPartyCatchActivity.notify.debug('startIdle')

    def finishIdle(self):
        DistributedPartyCatchActivity.notify.debug('finishIdle')

    def startActive(self):
        DistributedPartyCatchActivity.notify.debug('startActive')
        for avId in self.toonIds:
            if self.toonSDs.has_key(avId):
                toonSD = self.toonSDs[avId]
                toonSD.enter()
                toonSD.fsm.request('normal')

        self.fruitsCaught = 0
        self.dropIntervals = {}
        self.startDropTask()
        if base.localAvatar.doId in self.toonIds:
            self.putLocalAvatarInActivity()

    def finishActive(self):
        DistributedPartyCatchActivity.notify.debug('finishActive')
        self.stopDropTask()
        if hasattr(self, 'finishIval'):
            self.finishIval.pause()
            del self.finishIval
        if base.localAvatar.doId in self.toonIds:
            self.takeLocalAvatarOutOfActivity()
        for ival in self.dropIntervals.values():
            ival.finish()

        del self.dropIntervals

    def startConclusion(self):
        DistributedPartyCatchActivity.notify.debug('startConclusion')
        for avId in self.toonIds:
            if self.toonSDs.has_key(avId):
                toonSD = self.toonSDs[avId]
                toonSD.fsm.request('notPlaying')

        self.destroyCatchCollisions()
        if base.localAvatar.doId not in self.toonIds:
            return
        self.localToonExiting()
        if self.fruitsCaught >= self.numFruits:
            finishText = TTLocalizer.PartyCatchActivityFinishPerfect
        else:
            finishText = TTLocalizer.PartyCatchActivityFinish
        perfectTextSubnode = hidden.attachNewNode(self.__genText(finishText))
        perfectText = hidden.attachNewNode('perfectText')
        perfectTextSubnode.reparentTo(perfectText)
        frame = self.__textGen.getCardActual()
        offsetY = -abs(frame[2] + frame[3]) / 2.0
        perfectTextSubnode.setPos(0, 0, offsetY)
        perfectText.setColor(1, 0.1, 0.1, 1)

        def fadeFunc(t, text=perfectText):
            text.setColorScale(1, 1, 1, t)

        def destroyText(text=perfectText):
            text.removeNode()

        textTrack = Sequence(
            Func(perfectText.reparentTo, aspect2d),
            Parallel(
                LerpScaleInterval(perfectText,
                                  duration=0.5,
                                  scale=0.3,
                                  startScale=0.0),
                LerpFunctionInterval(fadeFunc,
                                     fromData=0.0,
                                     toData=1.0,
                                     duration=0.5)), Wait(2.0),
            Parallel(
                LerpScaleInterval(perfectText, duration=0.5, scale=1.0),
                LerpFunctionInterval(fadeFunc,
                                     fromData=1.0,
                                     toData=0.0,
                                     duration=0.5,
                                     blendType='easeIn')), Func(destroyText),
            WaitInterval(0.5))
        soundTrack = SoundInterval(self.sndPerfect)
        self.finishIval = Parallel(textTrack, soundTrack)
        self.finishIval.start()

    def finishConclusion(self):
        DistributedPartyCatchActivity.notify.debug('finishConclusion')
        if base.localAvatar.doId in self.toonIds:
            self.takeLocalAvatarOutOfActivity()
            base.cr.playGame.getPlace().fsm.request('walk')

    def showJellybeanReward(self, earnedAmount, jarAmount, message):
        if earnedAmount > 0:
            DistributedPartyActivity.showJellybeanReward(
                self, earnedAmount, jarAmount, message)
        else:
            base.cr.playGame.getPlace().fsm.request('walk')
Beispiel #54
0
    def create_text_section(self, text, tag='', x=0, y=0):
        # print(text, tag)
        self.text_node = TextNode('t')
        self.text_node_path = self.attachNewNode(self.text_node)
        try:
            self.text_node.setFont(self._font)
        except:
            pass  # default font

        if tag != '<>':
            tag = tag[1:-1]

            if tag.startswith('hsb('):  # set color based on numbers
                tag = tag[4:-1]
                hsb_values = tuple(float(e.strip()) for e in tag.split(','))
                self.current_color = color.color(*hsb_values)

            elif tag.startswith('rgb('):  # set color based on numbers
                tag = tag[4:-1]
                rgb_values = (float(e.strip()) for e in tag.split(','))
                self.current_color = color.rgba(*rgb_values)

            if tag.startswith('scale:'):
                scale = tag.split(':')[1]
                self.scale_override = float(scale)

            elif tag.startswith('image:'):
                texture_name = tag.split(':')[1]
                image = Entity(
                    parent=self.text_node_path,
                    name='inline_image',
                    model='quad',
                    texture=texture_name,
                    color=self.current_color,
                    scale=1,
                    # position=(x*self.size*self.scale_override, y*self.size*self.line_height),
                    origin=(.0, -.25),
                    add_to_scene_entities=False,
                )
                if not image.texture:
                    destroy(image)
                else:
                    self.images.append(image)
                    # self.text_node.remove_node()
                    # self.text_node = image
            else:
                if tag in self.text_colors:
                    self.current_color = self.text_colors[tag]

        self.text_node_path.setScale(self.scale_override * self.size)
        self.text_node.setText(text)
        self.text_node.setTextColor(self.current_color)
        self.text_node.setPreserveTrailingWhitespace(True)
        # self.text_node_path.setPos(
        #     x * self.size * self.scale_override,
        #     0,
        #     (y * self.size * self.line_height) - .75 * self.size)
        self.text_node_path.setPos(x * self.size * self.scale_override,
                                   (y * self.size * self.line_height) -
                                   .75 * self.size, 0)
        self.text_nodes.append(self.text_node_path)

        return self.text_node
Beispiel #55
0
    def load(self, loadModels=1, arenaModel='partyCatchTree'):
        self.notify.info('load()')
        DistributedPartyCatchActivity.notify.debug('PartyCatch: load')
        self.activityFSM = CatchActivityFSM(self)
        if __dev__:
            for o in xrange(3):
                print {
                    0: 'SPOTS PER PLAYER',
                    1: 'DROPS PER MINUTE PER SPOT DURING NORMAL DROP PERIOD',
                    2: 'DROPS PER MINUTE PER PLAYER DURING NORMAL DROP PERIOD'
                }[o]
                for i in xrange(1, self.FallRateCap_Players + 10):
                    self.defineConstants(forceNumPlayers=i)
                    numDropLocations = self.DropRows * self.DropColumns
                    numDropsPerMin = 60.0 / self.DropPeriod
                    if o == 0:
                        spotsPerPlayer = numDropLocations / float(i)
                        print '%2d PLAYERS: %s' % (i, spotsPerPlayer)
                    elif o == 1:
                        numDropsPerMinPerSpot = numDropsPerMin / numDropLocations
                        print '%2d PLAYERS: %s' % (i, numDropsPerMinPerSpot)
                    elif i > 0:
                        numDropsPerMinPerPlayer = numDropsPerMin / i
                        print '%2d PLAYERS: %s' % (i, numDropsPerMinPerPlayer)

        self.defineConstants()
        self.treesAndFence = loader.loadModel('phase_13/models/parties/%s' %
                                              arenaModel)
        self.treesAndFence.setScale(0.9)
        self.treesAndFence.find('**/fence_floor').setPos(0.0, 0.0, 0.1)
        self.treesAndFence.reparentTo(self.root)
        ground = self.treesAndFence.find('**/groundPlane')
        ground.setBin('ground', 1)
        DistributedPartyActivity.load(self)
        exitText = TextNode('PartyCatchExitText')
        exitText.setCardAsMargin(0.1, 0.1, 0.1, 0.1)
        exitText.setCardDecal(True)
        exitText.setCardColor(1.0, 1.0, 1.0, 0.0)
        exitText.setText(TTLocalizer.PartyCatchActivityExit)
        exitText.setTextColor(0.0, 8.0, 0.0, 0.9)
        exitText.setAlign(exitText.ACenter)
        exitText.setFont(ToontownGlobals.getBuildingNametagFont())
        exitText.setShadowColor(0, 0, 0, 1)
        exitText.setBin('fixed')
        if TTLocalizer.BuildingNametagShadow:
            exitText.setShadow(*TTLocalizer.BuildingNametagShadow)
        exitTextLoc = self.treesAndFence.find('**/loc_exitSignText')
        exitTextNp = exitTextLoc.attachNewNode(exitText)
        exitTextNp.setDepthWrite(0)
        exitTextNp.setScale(4)
        exitTextNp.setZ(-0.5)
        self.sign.reparentTo(self.treesAndFence.find('**/loc_eventSign'))
        self.sign.wrtReparentTo(self.root)
        self.avatarNodePath = NodePath('PartyCatchAvatarNodePath')
        self.avatarNodePath.reparentTo(self.root)
        self._avatarNodePathParentToken = 3
        base.cr.parentMgr.registerParent(self._avatarNodePathParentToken,
                                         self.avatarNodePath)
        self.toonSDs = {}
        self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow')
        self.dropObjModels = {}
        if loadModels:
            self.__loadDropModels()
        self.sndGoodCatch = base.loader.loadSfx(
            'phase_4/audio/sfx/SZ_DD_treasure.ogg')
        self.sndOof = base.loader.loadSfx(
            'phase_4/audio/sfx/MG_cannon_hit_dirt.ogg')
        self.sndAnvilLand = base.loader.loadSfx(
            'phase_4/audio/sfx/AA_drop_anvil_miss.ogg')
        self.sndPerfect = base.loader.loadSfx(
            'phase_4/audio/sfx/ring_perfect.ogg')
        self.__textGen = TextNode('partyCatchActivity')
        self.__textGen.setFont(ToontownGlobals.getSignFont())
        self.__textGen.setAlign(TextNode.ACenter)
        self.activityFSM.request('Idle')
Beispiel #56
0
 def _createPartyEditorPage(self):
     page = DirectFrame(self.frame)
     page.setName('PartyPlannerEditorPage')
     self.LayoutTitleLabel = DirectLabel(
         parent=page,
         relief=None,
         text=TTLocalizer.PartyPlannerEditorTitle,
         pos=self.gui.find('**/title_locator').getPos() +
         Point3(0.0, 0.0, 0.075),
         scale=self.titleScale)
     self.costLabel = DirectLabel(parent=page,
                                  pos=(-0.74, 0.0, 0.17),
                                  relief=None,
                                  text=TTLocalizer.PartyPlannerTotalCost %
                                  0,
                                  text_align=TextNode.ACenter,
                                  scale=TTLocalizer.PPcostLabel,
                                  textMayChange=True)
     self.partyGridBackground = DirectFrame(
         parent=page, relief=None, geom=self.gui.find('**/partyGrid_flat'))
     self.partyGroundsLabel = DirectLabel(
         parent=page,
         relief=None,
         text=TTLocalizer.PartyPlannerPartyGrounds,
         text_font=ToontownGlobals.getSignFont(),
         text_fg=VBase4(1.0, 0.0, 0.0, 1.0),
         text_scale=TTLocalizer.PPpartyGroundsLabel,
         pos=self.gui.find('**/step_05_partyGrounds_text_locator').getPos(),
         scale=0.1)
     self.activityBackground = DirectFrame(
         parent=page,
         relief=None,
         geom=self.gui.find('**/activitiesDecorations_flat1'),
         pos=(0.0, 0.0, 0.04))
     pos = self.gui.find('**/step_05_instructions_locator').getPos()
     self.instructionLabel = DirectLabel(
         parent=page,
         relief=None,
         text=' ',
         text_pos=(pos[0], pos[2]),
         text_scale=TTLocalizer.PPinstructionLabel,
         textMayChange=True,
         geom=self.gui.find('**/instructions_flat'))
     self.elementTitleLabel = DirectLabel(
         parent=page,
         relief=None,
         text=' ',
         pos=self.gui.find(
             '**/step_05_activitiesName_text_locator').getPos() +
         Point3(0.0, 0.0, 0.04),
         text_scale=TTLocalizer.PPelementTitleLabel,
         textMayChange=True)
     self.elementPriceNode = TextNode('ElementPrice')
     self.elementPriceNode.setAlign(TextNode.ALeft)
     self.elementPriceNode.setTextColor(0.0, 0.0, 0.0, 1.0)
     self.elementPriceNode.setFont(ToontownGlobals.getToonFont())
     self.elementPrice = page.attachNewNode(self.elementPriceNode)
     self.elementPrice.setScale(TTLocalizer.PPelementPriceNode)
     self.elementPrice.setPos(
         self.gui.find('**/step_05_activityPrice_text_locator').getPos() +
         Point3(-0.02, 0.0, 0.04))
     self.elementDescriptionNode = TextNode('ElementDescription')
     self.elementDescriptionNode.setAlign(TextNode.ACenter)
     self.elementDescriptionNode.setWordwrap(8)
     self.elementDescriptionNode.setFont(ToontownGlobals.getToonFont())
     self.elementDescriptionNode.setTextColor(0.0, 0.0, 0.0, 1.0)
     self.elementDescription = page.attachNewNode(
         self.elementDescriptionNode)
     self.elementDescription.setScale(TTLocalizer.PPelementDescription)
     self.elementDescription.setPos(
         self.gui.find(
             '**/step_05_activityDescription_text_locator').getPos() +
         Point3(0.0, 0.0, 0.04))
     self.totalMoney = base.localAvatar.getTotalMoney()
     catalogGui = loader.loadModel('phase_5.5/models/gui/catalog_gui')
     self.beanBank = DirectLabel(parent=page,
                                 relief=None,
                                 text=str(self.totalMoney),
                                 text_align=TextNode.ARight,
                                 text_scale=0.075,
                                 text_fg=(0.95, 0.95, 0, 1),
                                 text_shadow=(0, 0, 0, 1),
                                 text_pos=(0.495, -0.53),
                                 text_font=ToontownGlobals.getSignFont(),
                                 textMayChange=True,
                                 image=catalogGui.find('**/bean_bank'),
                                 image_scale=(0.65, 0.65, 0.65),
                                 scale=0.9,
                                 pos=(-0.75, 0.0, 0.6))
     catalogGui.removeNode()
     del catalogGui
     self.accept(localAvatar.uniqueName('moneyChange'), self.__moneyChange)
     self.accept(localAvatar.uniqueName('bankMoneyChange'),
                 self.__moneyChange)
     self.partyEditor = PartyEditor(self, page)
     self.partyEditor.request('Hidden')
     pos = self.gui.find('**/step_05_add_text_locator').getPos()
     self.elementBuyButton = DirectButton(
         parent=page,
         relief=None,
         text=TTLocalizer.PartyPlannerBuy,
         text_pos=(pos[0], pos[2]),
         text_scale=TTLocalizer.PPelementBuyButton,
         geom=(self.gui.find('**/add_up'), self.gui.find('**/add_down'),
               self.gui.find('**/add_rollover')),
         geom3_color=VBase4(0.5, 0.5, 0.5, 1.0),
         textMayChange=True,
         pos=(0.0, 0.0, 0.04),
         command=self.partyEditor.buyCurrentElement)
     self.okWithPartyGroundsLayoutEvent = 'okWithPartyGroundsLayoutEvent'
     self.accept(self.okWithPartyGroundsLayoutEvent,
                 self.okWithPartyGroundsLayout)
     self.okWithGroundsGui = TTDialog.TTGlobalDialog(
         dialogName=self.uniqueName('PartyEditorOkGui'),
         doneEvent=self.okWithPartyGroundsLayoutEvent,
         message=TTLocalizer.PartyPlannerOkWithGroundsLayout,
         style=TTDialog.YesNo,
         okButtonText=OTPLocalizer.DialogYes,
         cancelButtonText=OTPLocalizer.DialogNo)
     self.okWithGroundsGui.doneStatus = ''
     self.okWithGroundsGui.hide()
     return page
Beispiel #57
0
class Sprite(NodePath, DirectObject):
    #- Just constant identifiers
    MouseLeftDown = 'left-down'
    MouseLeftUp = 'left-up'
    MouseLeftClick = 'left-click'
    MouseCenterDown = 'center-down'
    MouseCenterUp = 'center-up'
    MouseCenterClick = 'center-click'
    MouseRightDown = 'right-down'
    MouseRightUp = 'right-up'
    MouseRightClick = 'right-click'
    MouseFourDown = 'four-down'
    MouseFourUp = 'four-up'
    MouseFourClick = 'four-click'
    MouseFiveDown = 'five-down'
    MouseFiveUp = 'five-up'
    MouseFiveClick = 'five-click'
    MouseScrollUp = 'scroll-up'
    MouseScrollDown = 'scroll-down'
    MouseEnter = 'enter'
    MouseExit = 'exit'
    MouseWithin = 'within'
    MouseWithout = 'without'
    StateDefault = 'state-default'
    StateHover = 'state-hover'
    StateClick = 'state-click'
    StateFocus = 'state-focus'
    StateDisabled = 'state-disabled'

    def __init__(self, name):
        NodePath.__init__(self, name)
        DirectObject.__init__(self)
        self.setPythonTag('Sprite', self)

        global SpriteCounter
        SpriteCounter += 1
        self.__id = int(SpriteCounter)

        #- Use PGItem to detect mouse and keyboard input via PGTop (eg, aspect2d, pixel2d, etc)
        self.__pgItem = PGItem(name)
        self.__pgItem.setActive(True)
        self.__pgItemNp = self.attachNewNode(self.__pgItem)

        #- Use TextNode to generate both text and cards for displaying background images
        self.__textNode = TextNode(name)
        self.__textNodeNp = None
        #self.__textNodeNp = self.attachNewNode(self.__textNode)
        #self.__textNode.setCardDecal(True) #- This is what we would do, should Sprite support being non-under PGTop

        self.accept(self.__pgItem.getPressEvent(MouseButton.one()),
                    self.__onMouse, [Sprite.MouseLeftDown])
        self.accept(self.__pgItem.getPressEvent(MouseButton.two()),
                    self.__onMouse, [Sprite.MouseCenterDown])
        self.accept(self.__pgItem.getPressEvent(MouseButton.three()),
                    self.__onMouse, [Sprite.MouseRightDown])
        self.accept(self.__pgItem.getPressEvent(MouseButton.four()),
                    self.__onMouse, [Sprite.MouseFourDown])
        self.accept(self.__pgItem.getPressEvent(MouseButton.five()),
                    self.__onMouse, [Sprite.MouseFiveDown])

        self.accept(self.__pgItem.getReleaseEvent(MouseButton.one()),
                    self.__onMouse, [Sprite.MouseLeftUp])
        self.accept(self.__pgItem.getReleaseEvent(MouseButton.two()),
                    self.__onMouse, [Sprite.MouseCenterUp])
        self.accept(self.__pgItem.getReleaseEvent(MouseButton.three()),
                    self.__onMouse, [Sprite.MouseRightUp])
        self.accept(self.__pgItem.getReleaseEvent(MouseButton.four()),
                    self.__onMouse, [Sprite.MouseFourUp])
        self.accept(self.__pgItem.getReleaseEvent(MouseButton.five()),
                    self.__onMouse, [Sprite.MouseFiveUp])

        self.accept(self.__pgItem.getPressEvent(MouseButton.wheelDown()),
                    self.__onMouse, [Sprite.MouseScrollDown])
        self.accept(self.__pgItem.getPressEvent(MouseButton.wheelUp()),
                    self.__onMouse, [Sprite.MouseScrollUp])

        self.accept(self.__pgItem.getEnterEvent(), self.__onMouse,
                    [Sprite.MouseEnter])
        self.accept(self.__pgItem.getExitEvent(), self.__onMouse,
                    [Sprite.MouseExit])
        self.accept(self.__pgItem.getWithinEvent(), self.__onMouse,
                    [Sprite.MouseWithin])
        self.accept(self.__pgItem.getWithoutEvent(), self.__onMouse,
                    [Sprite.MouseWithout])

        self.__beastDebug = ConfigVariableBool('beast-debug', False).getValue()

        self.__mouseInside = False
        self.__disabled = False

        #- Setup state configuration
        self.__lastStateOptions = None
        self.__state = None
        self.__states = {
            'default': SpriteOptions(),
            'hover': SpriteOptions(),
            'click': SpriteOptions(),
            'focus': SpriteOptions(),
            'disabled': SpriteOptions(),
        }
        self.updateToState('default')

    def setDirty(self, dirty=True):
        if dirty:
            self.setTag('dirty', '')
        else:
            self.clearTag('dirty')

    def setDisabled(self, disabled):
        self.__disabled = disabled
        if self.__disabled:
            self.updateToState('disabled')
        else:
            #- FIXME! Account for focus?
            self.updateToState('default')

    def isDisabled(self):
        return self.__disabled

    def bind(self, event, method, extraArgs=[], onlyOnce=False):
        actualEvent = self.getEvent(event)
        if onlyOnce:
            self.acceptOnce(event, method, extraArgs=extraArgs)
        else:
            self.accept(event, method, extraArgs=extraArgs)

    def unbind(self, event):
        actualEvent = self.getEvent(event)
        self.ignore(actualEvent)

    def getEvent(self, event):
        return 'Sprite-' + str(self.__id) + '-' + self.getName() + '-' + event

    def __onMouse(self, event, mwr):
        if event == Sprite.MouseEnter:
            self.__mouseInside = True
        elif event == Sprite.MouseExit:
            self.__mouseInside = False

        actualEvents = []
        actualEvents.append(event)

        if self.__mouseInside:
            if event == Sprite.MouseLeftUp:
                actualEvents.append(Sprite.MouseLeftClick)
            elif event == Sprite.MouseCenterUp:
                actualEvents.append(Sprite.MouseCenterClick)
            elif event == Sprite.MouseRightUp:
                actualEvents.append(Sprite.MouseRightClick)
            elif event == Sprite.MouseFourUp:
                actualEvents.append(Sprite.MouseFourClick)
            elif event == Sprite.MouseFiveUp:
                actualEvents.append(Sprite.MouseFiveClick)

        #- Handle state changing
        for event in actualEvents:
            if self.__state == 'default':
                if event == Sprite.MouseEnter:
                    self.updateToState('hover')
            elif self.__state == 'hover':
                if event == Sprite.MouseExit:
                    self.updateToState('default')
                if event == Sprite.MouseLeftDown:
                    self.updateToState('click')
            elif self.__state == 'click':
                if event == Sprite.MouseLeftClick:
                    #                    self.updateToState('focus')
                    self.updateToState('hover')
                if event == Sprite.MouseLeftUp and self.__mouseInside == False:
                    #                    self.updateToState('focus')
                    self.updateToState('default')

        #- Finally, we can send out user events
        for event in actualEvents:
            messenger.send(self.getEvent(event))

    def updateToState(self, newState=None):
        if newState == self.__state:
            return
        if newState:
            self.__state = newState
        if self.__beastDebug:
            print self.__state, globalClock.getFrameCount()
        messenger.send(self.getEvent('state-' + self.__state))
        defaultOptions = self.__states['default']
        hoverOptions = self.__states['hover']
        clickOptions = self.__states['click']
        focusOptions = self.__states['focus']
        disabledOptions = self.__states['disabled']

        if self.__state == 'default':
            self._applySpriteOptions(SpriteOptions.combine(defaultOptions))
        elif self.__state == 'hover':
            self._applySpriteOptions(
                SpriteOptions.combine(defaultOptions, hoverOptions))
        elif self.__state == 'click':
            self._applySpriteOptions(
                SpriteOptions.combine(defaultOptions, hoverOptions,
                                      clickOptions))
        elif self.__state == 'focus':
            self._applySpriteOptions(
                SpriteOptions.combine(defaultOptions, focusOptions))
        elif self.__state == 'disabled':
            self._applySpriteOptions(
                SpriteOptions.combine(defaultOptions, disabledOptions))

    def _applySpriteOptions(self, options):
        dirty = False
        if options.options.values() == self.__lastStateOptions:
            return
        else:
            self.__lastStateOptions = options.options.values()
            self.setDirty()
            dirty = True

        #- First we do checks for size
        if options.hasSize():
            self.__pgItem.setActive(True)  #- It has a size, so it's active
            x, y = options.getSize()
            self.__pgItem.setFrame(0, x, -y, 0)
            #- Set both the card and frame bounds to match the size specified
            self.__textNode.setCardActual(0, x, -y, 0)

            if options.hasBorderColor():
                #- They want a border, no matter what
                self.__textNode.setFrameActual(0, x, -y, 0)
                if options.hasBorderWidth():
                    self.__textNode.setFrameLineWidth(options.getBorderWidth())
                else:
                    self.__textNode.setFrameLineWidth(1)
            else:
                #- They want no border
                self.__textNode.clearFrame()
                self.__textNode.setFrameLineWidth(0)  #- Unimportant I think
        else:
            self.__pgItem.setActive(False)  #- It has no size, it's un active
            self.__pgItem.setFrame(0, 0, 0, 0)
            self.__textNode.clearCard()
            self.__textNode.clearFrame()

        if options.hasFont():
            self.__textNode.setFont(options.getFont())
        else:
            self.__textNode.clearFont()

        if options.hasFontSize():
            #- FIXME! change for point2d later
            textNodeScale = 1.0 / options.getFontSize()  #- Applied later
        #    #self.__textNodeNp.setScale(1.0 / options.getFontSize())
        # FIXME? Make sure it's 4 spaces    self.__textNode.setTabWidth(options.getFontSize() * 4.0)
        else:
            textNodeScale = 1.0
        #    #self.__textNodeNp.setScale(1.0)

        if options.hasBackgroundColor():
            color = options.getBackgroundColor().getAsFloat()
            self.__textNode.setCardColor(*color)
        else:
            if options.hasSize():
                self.__textNode.setCardColor(1, 1, 1, 1)  #- White
            else:
                self.__textNode.setCardColor(0, 0, 0, 0)  #- Clear

        if options.hasBorderColor():
            color = options.getBorderColor().getAsFloat()
            self.__textNode.setFrameColor(*color)
        else:
            self.__textNode.setFrameColor(0, 0, 0, 0)  #- Clear

        if options.hasText():
            text = options.getText()
            self.__textNode.setWtext(options.getText())

            if options.hasTextPadding():
                px, py = options.getTextPadding()
            else:
                px, py = (0, 0)

            #- Set sizes, even if they have no color
            self.__textNode.setCardAsMargin(px, px, py, py)
            self.__textNode.setFrameAsMargin(px, px, py, py)

            l, r, b, t = self.__textNode.getCardActual()
            #- Offset the TextNode so it only extends right and down

            #- FIXME! change for point2d later? (Does scale apply there even haha?)
            s = textNodeScale
            l, r, b, t = l * s, r * s, b * s, t * s

            textNodeX = -l  #- Applied later
            textNodeZ = -t  #- Applied later
            #self.__textNodeNp.setX(-l)
            #self.__textNodeNp.setZ(-t)
            self.__pgItem.setActive(True)  #- It has a size now, it's active
            self.__pgItem.setFrame(0, -l + r, -t + b, 0)
        else:
            self.__textNode.setWtext(
                u' '
            )  #- It's important to have a space, otherwise no card is rendered!
            textNodeX = 0  #- Applied later
            textNodeZ = 0  #- Applied later
            #self.__textNodeNp.setX(0)
            #self.__textNodeNp.setZ(0)
            if not options.hasSize():
                self.__pgItem.setFrame(0, 0, 0, 0)

        if options.hasTextAlign():
            align = options.getTextAlign()
            if align == 'left':
                self.__textNode.setAlign(TextNode.ALeft)
            elif align == 'center':
                self.__textNode.setAlign(TextNode.ACenter)
            elif align == 'right':
                self.__textNode.setAlign(TextNode.ARight)
        else:
            self.__textNode.clearAlign()

        if options.hasTextColor():
            color = options.getTextColor().getAsFloat()
            self.__textNode.setTextColor(*color)
            #self.__textNodeNp.setColor(*color)
            #else:
            self.__textNode.setTextColor(0, 0, 0, 1)  #- Black
        #    self.__textNodeNp.clearColor()

        if options.hasTextSmallCaps():
            self.__textNode.setSmallCaps(options.getTextSmallCaps())
        else:
            self.__textNode.clearSmallCaps()

        if options.hasTextSmallCapsScale():
            self.__textNode.setSmallCapsScale(options.getTextSmallCapsScale())
        else:
            self.__textNode.clearSmallCapsScale()

        if options.hasTextSlant():
            self.__textNode.setSlant(options.getTextSlant())
        else:
            self.__textNode.clearSlant()

        if options.hasTextUnderline():
            self.__textNode.setUnderscore(options.getTextUnderline())
        else:
            self.__textNode.clearUnderscore()

        if options.hasTextShadow():
            self.__textNode.setShadow(*options.getTextShadow())
        else:
            self.__textNode.clearShadow()

        if options.hasTextShadowColor():
            color = options.getTextShadowColor().getAsFloat()
            self.__textNode.setShadowColor(*color)
        else:
            self.__textNode.clearShadowColor()

        if self.__textNodeNp:
            self.__textNodeNp.remove()
        self.__textNodeNp = self.attachNewNode(self.__textNode.generate())
        self.__textNodeNp.setScale(textNodeScale)
        self.__textNodeNp.setX(textNodeX)
        self.__textNodeNp.setZ(textNodeZ)
        '''
        def setup(self, textNodeScale, textNodeX, textNodeZ):
            print 'getting lock...'
            base.textThreadLock.acquire()
            print 'Got lock'
            if self.__textNodeNp:
                self.__textNodeNp.remove()
            self.__textNodeNp = self.attachNewNode('foobar')
            #textNode.generate()
            print 'yes, it generated'
            base.textThreadLock.release()
        '''
        #self.__textNodeNp = self.attachNewNode(self.__textNode.generate())
        #self.__textNodeNp.setScale(textNodeScale)
        #self.__textNodeNp.setX(textNodeX)
        #self.__textNodeNp.setZ(textNodeZ)
        '''
        import direct.stdpy.threading
        t = threading.Thread(target=setup, args=(self, textNodeScale, textNodeX, textNodeZ))
        t.start()
        '''

        if dirty:
            messenger.send('beastCollectionUpdate')

    def getOptions(self, state):
        return self.__states[state]

    def getCurrentOptions(self):
        return self.__states[self.__state]

    def getCurrentState(self):
        return self.__state

    def getPgItem(self):
        return self.__pgItem

    def getPgItemNp(self):
        return self.__pgItemNp

    def getTextNode(self):
        return self.__textNode

    def getTextNodeNp(self):
        return self.__textNodeNp

    @staticmethod
    def destroyChildren(np):
        for child in np.getChildren():
            if child.hasPythonTag('Sprite'):
                sprite = child.getPythonTag('Sprite')
                sprite.destroy()

    def destroy(self):
        self.clearPythonTag('Sprite')
        self.ignoreAll()
        Sprite.destroyChildren(self)
        self.remove()
Beispiel #58
0
class GUI(object):
    """ Handles the gui elements like showing the current stage """
    def __init__(self, control):

        self.control = control
        self.gui_node = pixel2d.attach_new_node("GUI")
        self.gui_node.hide()
        self.gui_node.set_transparency(True)

        roboto_light = loader.loadFont("res/Roboto-Light.ttf")
        roboto_light.set_scale_factor(1)
        roboto_light.set_pixels_per_unit(120)

        self.text_stage = TextNode("TextStage")
        self.text_stage.set_text("Stage 1")
        self.text_stage.set_align(TextNode.A_left)
        self.text_stage.set_text_color(1, 1, 1, 1)
        self.text_stage.set_font(roboto_light)
        self.text_stage_np = self.gui_node.attach_new_node(self.text_stage)
        self.text_stage_np.set_scale(80.0)
        self.text_stage_np.set_pos(60, 0, -120)

        self.anim = None

    def show(self):
        self.gui_node.show()
        if self.anim is not None:
            self.anim.finish()
        self.anim = Sequence(
            LerpColorScaleInterval(self.gui_node,
                                   0.2,
                                   Vec4(1),
                                   Vec4(1, 1, 1, 0),
                                   blendType="easeInOut"))
        self.anim.start()

    def hide(self):
        self.gui_node.hide()
        if self.anim is not None:
            self.anim.finish()
        self.anim = Sequence(
            LerpColorScaleInterval(self.gui_node,
                                   0.2,
                                   Vec4(1, 1, 1, 0),
                                   Vec4(1),
                                   blendType="easeInOut"))
        self.anim.start()

    def set_stage(self, stage_nr):
        print("Setting stage", stage_nr)

        Sequence(
            LerpColorScaleInterval(self.text_stage_np,
                                   0.4,
                                   Vec4(1, 1, 1, 0),
                                   Vec4(1),
                                   blendType="easeInOut"),
            Func(lambda *args: self.text_stage.set_text("Stage " + str(stage_nr
                                                                       ))),
            LerpColorScaleInterval(self.text_stage_np,
                                   0.4,
                                   Vec4(1),
                                   Vec4(1, 1, 1, 0),
                                   blendType="easeInOut"),
        ).start()
Beispiel #59
0
    def __init__(self, rendering: bool):
        """
        Constructor

        :param rendering: boolean indicating whether to use RenderPipeline or default Panda3d as visualization-module.
        """
        super().__init__(self)
        self.dir = Filename.fromOsSpecific(
            pyrado.PANDA_ASSETS_DIR).getFullpath()

        # Initialize RenderPipeline
        if rendering:
            sys.path.insert(0, pyrado.RENDER_PIPELINE_DIR)
            from rpcore import RenderPipeline

            self.render_pipeline = RenderPipeline()
            self.render_pipeline.pre_showbase_init()
            self.render_pipeline.set_loading_screen_image(
                osp.join(self.dir, "logo.png"))
            self.render_pipeline.settings["pipeline.display_debugger"] = False
            self.render_pipeline.create(self)
            self.render_pipeline.daytime_mgr.time = "17:00"
        else:
            self.render_pipeline = None

        # Activate antialiasing
        self.render.setAntialias(AntialiasAttrib.MAuto)

        # Set window properties
        self.windowProperties = WindowProperties()
        self.windowProperties.setForeground(True)
        self.windowProperties.setTitle("Experiment")

        # Set background color
        self.setBackgroundColor(1, 1, 1)

        # Configuration of the lighting
        self.directionalLight1 = DirectionalLight("directionalLight")
        self.directionalLightNP1 = self.render.attachNewNode(
            self.directionalLight1)
        self.directionalLightNP1.setHpr(0, -8, 0)
        self.render.setLight(self.directionalLightNP1)

        self.directionalLight2 = DirectionalLight("directionalLight")
        self.directionalLightNP2 = self.render.attachNewNode(
            self.directionalLight2)
        self.directionalLightNP2.setHpr(180, -20, 0)
        self.render.setLight(self.directionalLightNP2)

        self.ambientLight = AmbientLight("ambientLight")
        self.ambientLightNP = self.render.attachNewNode(self.ambientLight)
        self.ambientLight.setColor((0.1, 0.1, 0.1, 1))
        self.render.setLight(self.ambientLightNP)

        # Create a text node displaying the physic parameters on the top left of the screen
        self.text = TextNode("parameters")
        self.textNodePath = aspect2d.attachNewNode(self.text)
        self.text.setTextColor(0, 0, 0, 1)  # black
        self.textNodePath.setScale(0.07)
        self.textNodePath.setPos(-1.9, 0, 0.9)

        # Configure trace
        self.trace = LineSegs()
        self.trace.setThickness(3)
        self.trace.setColor(0.8, 0.8, 0.8)  # light grey
        self.lines = self.render.attachNewNode("Lines")
        self.last_pos = None

        # Adds one instance of the update function to the task-manager, thus initializes the animation
        self.taskMgr.add(self.update, "update")
Beispiel #60
0
class PartyCog(FSM):
    notify = directNotify.newCategory('PartyCog')
    HpTextGenerator = TextNode('HpTextGenerator')
    hpText = None
    height = 7

    def __init__(self,
                 parentNode,
                 id,
                 bounceSpeed=3,
                 bounceHeight=1,
                 rotateSpeed=1,
                 heightShift=1,
                 xMoveSpeed=0,
                 xMoveDistance=0,
                 bounceOffset=0):
        self.id = id
        FSM.__init__(self, 'PartyCogFSM-%d' % self.id)
        self.showFacingStatus = False
        self.xMoveSpeed = xMoveSpeed
        self.xMoveDistance = xMoveDistance
        self.heightShift = heightShift
        self.bounceSpeed = bounceSpeed
        self.bounceHeight = bounceHeight
        self.rotateSpeed = rotateSpeed
        self.parentNode = parentNode
        self.bounceOffset = bounceOffset
        self.hitInterval = None
        self.kaboomTrack = None
        self.resetRollIval = None
        self.netTimeSentToStartByHit = 0
        self.load()
        self.request('Down')
        return

    def load(self):
        self.root = NodePath('PartyCog-%d' % self.id)
        self.root.reparentTo(self.parentNode)
        path = 'phase_13/models/parties/cogPinata_'
        self.actor = Actor(
            path + 'actor', {
                'idle': path + 'idle_anim',
                'down': path + 'down_anim',
                'up': path + 'up_anim',
                'bodyHitBack': path + 'bodyHitBack_anim',
                'bodyHitFront': path + 'bodyHitFront_anim',
                'headHitBack': path + 'headHitBack_anim',
                'headHitFront': path + 'headHitFront_anim'
            })
        self.actor.reparentTo(self.root)
        self.temp_transform = Mat4()
        self.head_locator = self.actor.attachNewNode('temphead')
        self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75)
        self.bodyColl.setTangible(1)
        self.bodyCollNode = CollisionNode('PartyCog-%d-Body-Collision' %
                                          self.id)
        self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.bodyCollNode.addSolid(self.bodyColl)
        self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode)
        self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5)
        self.headColl.setTangible(1)
        self.headCollNode = CollisionNode('PartyCog-%d-Head-Collision' %
                                          self.id)
        self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.headCollNode.addSolid(self.headColl)
        self.headCollNodePath = self.root.attachNewNode(self.headCollNode)
        self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0)
        self.arm1Coll.setTangible(1)
        self.arm1CollNode = CollisionNode('PartyCog-%d-Arm1-Collision' %
                                          self.id)
        self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm1CollNode.addSolid(self.arm1Coll)
        self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode)
        self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0)
        self.arm2Coll.setTangible(1)
        self.arm2CollNode = CollisionNode('PartyCog-%d-Arm2-Collision' %
                                          self.id)
        self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm2CollNode.addSolid(self.arm2Coll)
        self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode)
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splatType = globalPropPool.getPropType(splatName)
        self.pieHitSound = globalBattleSoundCache.getSound(
            'AA_wholepie_only.ogg')
        self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.ogg')
        self.hole = loader.loadModel('phase_13/models/parties/cogPinataHole')
        self.hole.setTransparency(True)
        self.hole.setP(-90.0)
        self.hole.setScale(3)
        self.hole.setBin('ground', 3)
        self.hole.reparentTo(self.parentNode)

    def unload(self):
        self.request('Off')
        self.clearHitInterval()
        if self.hole is not None:
            self.hole.removeNode()
            self.hole = None
        if self.actor is not None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None
        if self.root is not None:
            self.root.removeNode()
            self.root = None
        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.kaboomTrack = None
        if self.resetRollIval is not None and self.resetRollIval.isPlaying():
            self.resetRollIval.finish()
        self.resetRollIval = None
        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.finish()
        self.hitInterval = None
        del self.upSound
        del self.pieHitSound
        return

    def enterStatic(self):
        pass

    def exitStatic(self):
        pass

    def enterActive(self, startTime):
        self.root.setR(0.0)
        updateTask = Task.Task(self.updateTask)
        updateTask.startTime = startTime
        taskMgr.add(updateTask, 'PartyCog.update-%d' % self.id)

    def exitActive(self):
        taskMgr.remove('PartyCog.update-%d' % self.id)
        taskMgr.remove('PartyCog.bounceTask-%d' % self.id)
        self.clearHitInterval()
        self.resetRollIval = self.root.hprInterval(0.5,
                                                   Point3(
                                                       self.root.getH(), 0.0,
                                                       0.0),
                                                   blendType='easeInOut')
        self.resetRollIval.start()
        self.actor.stop()

    def enterDown(self):
        if self.oldState == 'Off':
            downAnimControl = self.actor.getAnimControl('down')
            self.actor.pose('down', downAnimControl.getNumFrames() - 1)
            return
        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(
            LerpFunc(self.setAlongSpline,
                     duration=1.0,
                     fromData=self.currentT,
                     toData=0.0),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=endScale,
                              startScale=startScale,
                              blendType='easeIn'),
            Parallel(
                SoundInterval(self.upSound,
                              volume=0.6,
                              node=self.actor,
                              cutOff=PartyGlobals.PARTY_COG_CUTOFF),
                ActorInterval(self.actor, 'down', loop=0)),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=Point3(3, 3, 3),
                              startScale=endScale,
                              blendType='easeOut'))
        self.hitInterval.start()

    def exitDown(self):
        self.root.setR(0.0)
        self.root.setH(0.0)
        self.targetDistance = 0.0
        self.targetFacing = 0.0
        self.currentT = 0.0
        self.setAlongSpline(0.0)
        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=endScale,
                              startScale=startScale,
                              blendType='easeIn'),
            Parallel(
                SoundInterval(self.upSound,
                              volume=0.6,
                              node=self.actor,
                              cutOff=PartyGlobals.PARTY_COG_CUTOFF),
                ActorInterval(self.actor, 'up', loop=0)),
            Func(self.actor.loop, 'idle'),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=Point3(3, 3, 3),
                              startScale=endScale,
                              blendType='easeOut'))
        self.hitInterval.start()

    def filterDown(self, request, args):
        if request == 'Down':
            return None
        else:
            return self.defaultFilter(request, args)
        return None

    def setEndPoints(self, start, end, amplitude=1.7):
        self.sinAmplitude = amplitude
        self.sinPeriod = (end.getX() - start.getX()) / 2
        self.sinDisplacement = start.getY()
        self.startPoint = start
        self.endPoint = end
        self.currentT = 0.0
        self.targetDistance = 0.0
        self.currentFacing = 0.0
        self.targetFacing = 0.0
        self.setAlongSpline(self.currentT)
        self.hole.setPos(self.root.getPos())
        self.hole.setZ(0.02)

    def rockBackAndForth(self, task):
        t = task.startTime + task.time
        angle = math.sin(t) * 20.0
        self.root.setR(angle)
        return task.cont

    def updateDistance(self, distance):
        self.targetDistance = clamp(distance, -1.0, 1.0)

    def updateTask(self, task):
        self.rockBackAndForth(task)
        if self.targetDistance > self.currentT:
            self.currentT += min(0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)
        elif self.targetDistance < self.currentT:
            self.currentT += max(-0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)
        if self.currentT < 0.0:
            self.targetFacing = -90.0
        elif self.currentT > 0.0:
            self.targetFacing = 90.0
        else:
            self.targetFacing = 0.0
        if self.targetFacing > self.currentFacing:
            self.currentFacing += min(10,
                                      self.targetFacing - self.currentFacing)
        elif self.targetFacing < self.currentFacing:
            self.currentFacing += max(-10,
                                      self.targetFacing - self.currentFacing)
        self.root.setH(self.currentFacing)
        return task.cont

    def setAlongSpline(self, t):
        t = t + 1.0
        dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0
        x = self.startPoint.getX() + t * dist
        y = self.startPoint.getY() - math.sin(
            t * 2 * math.pi) * self.sinAmplitude
        self.root.setPos(x, y, 0)

    def startBounce(self):
        taskMgr.add(self.bounce, 'PartyCog.bounceTask-%d' % self.id)

    def bounce(self, task):
        self.root.setZ(
            math.sin((self.bounceOffset + task.time) * self.bounceSpeed) *
            self.bounceHeight + self.heightShift)
        return task.cont

    def setPos(self, position):
        self.root.setPos(position)

    def respondToPieHit(self, timestamp, position, hot=False, direction=1.0):
        if self.netTimeSentToStartByHit < timestamp:
            self.__showSplat(position, direction, hot)
            if self.netTimeSentToStartByHit < timestamp:
                self.netTimeSentToStartByHit = timestamp
        else:
            self.notify.debug(
                'respondToPieHit self.netTimeSentToStartByHit = %s' %
                self.netTimeSentToStartByHit)

    def clearHitInterval(self):
        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.clearToInitial()
        return

    def __showSplat(self, position, direction, hot=False):
        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.clearHitInterval()
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splat.reparentTo(render)
        self.splat.setPos(self.root, position)
        self.splat.setAlphaScale(1.0)
        if not direction == 1.0:
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0])
            if self.currentFacing > 0.0:
                facing = 'HitFront'
            else:
                facing = 'HitBack'
        else:
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1])
            if self.currentFacing > 0.0:
                facing = 'HitBack'
            else:
                facing = 'HitFront'
        if hot:
            targetscale = 0.75
            part = 'head'
        else:
            targetscale = 0.5
            part = 'body'

        def setSplatAlpha(amount):
            self.splat.setAlphaScale(amount)

        self.hitInterval = Sequence(
            ActorInterval(self.actor, part + facing, loop=0),
            Func(self.actor.loop, 'idle'))
        self.hitInterval.start()
        self.kaboomTrack = Parallel(
            SoundInterval(self.pieHitSound,
                          volume=1.0,
                          node=self.actor,
                          cutOff=PartyGlobals.PARTY_COG_CUTOFF),
            Sequence(
                Func(self.splat.showThrough),
                Parallel(
                    Sequence(
                        LerpScaleInterval(self.splat,
                                          duration=0.175,
                                          scale=targetscale,
                                          startScale=Point3(0.1, 0.1, 0.1),
                                          blendType='easeOut'), Wait(0.175)),
                    Sequence(
                        Wait(0.1),
                        LerpFunc(setSplatAlpha,
                                 duration=1.0,
                                 fromData=1.0,
                                 toData=0.0,
                                 blendType='easeOut'))),
                Func(self.splat.cleanup), Func(self.splat.removeNode)))
        self.kaboomTrack.start()
        return

    def showHitScore(self, number, scale=1):
        if number <= 0:
            return
        if self.hpText:
            self.hideHitScore()
        self.HpTextGenerator.setFont(ToontownGlobals.getSignFont())
        if number < 0:
            self.HpTextGenerator.setText(str(number))
        else:
            self.HpTextGenerator.setText('+' + str(number))
        self.HpTextGenerator.clearShadow()
        self.HpTextGenerator.setAlign(TextNode.ACenter)
        r = 1
        g = 1
        b = 0
        a = 1
        self.HpTextGenerator.setTextColor(r, g, b, a)
        self.hpTextNode = self.HpTextGenerator.generate()
        self.hpText = render.attachNewNode(self.hpTextNode)
        self.hpText.setScale(scale)
        self.hpText.setBillboardPointEye()
        self.hpText.setBin('fixed', 100)
        self.hpText.setPos(self.root, 0, 0, self.height / 2)
        seq = Sequence(
            self.hpText.posInterval(
                0.25,
                Point3(self.root.getX(render), self.root.getY(render),
                       self.root.getZ(render) + self.height + 1.0),
                blendType='easeOut'), Wait(0.25),
            self.hpText.colorInterval(0.1, Vec4(r, g, b, 0)),
            Func(self.__hideHitScore))
        seq.start()

    def hideHitScore(self):
        if self.hpText:
            taskMgr.remove('PartyCogHpText' + str(self.id))
            self.hpText.removeNode()
            self.hpText = None
        return

    def getHeadLocation(self):
        self.actor.getJoints(jointName='head')[0].getNetTransform(
            self.temp_transform)
        self.head_locator.setMat(self.temp_transform)
        return self.head_locator.getZ(self.root)