def test_windows_setup(self):
        self.store.storeNode('files/node.bam', '', 'window_r')
        self.store.storeNode('files/hood_node.bam', '', 'window_l')

        windows = DNAWindows('windows')

        x = .1
        y = .4
        np = NodePath('window_root')
        code = 'window_l'
        scale = 1.25
        color = Vec4(.842, .167, .361, 1)

        windows.makeWindows(x, y, np, code, scale, color, self.store, False)

        # Check if the nodes attributes are correct
        model = np.find('**/node')
        self.assertFalse(model.isEmpty())
        self.assertEqual(model.getPos(np), Point3(x, 0, y))
        self.assertEqual(model.getScale(np), Vec3(scale))

        # Now test with flip = True
        np.removeNode()
        np = NodePath('window_root')

        windows.makeWindows(x, y, np, code, scale, color, self.store, True)
        # Check if the nodes attributes are correct
        model = np.find('**/hood_node')
        self.assertFalse(model.isEmpty())
        self.assertEqual(model.getPos(np), Point3(x, 0, y))
        self.assertEqual(model.getScale(np), Vec3(scale))
Пример #2
0
def changeModel(newmodel):
    tempParent=NodePath('')
    newModel=loader.loadModel(newmodel)
    newModel.findAllMatches('**/+GeomNode').reparentTo(tempParent)
    tempParent.setScale(1.5/tempParent.getBounds().getRadius())
    tempParent.setPos(-tempParent.getBounds().getCenter())
    tempParent.flattenStrong()
    tempParent.find('**/+GeomNode').node().replaceNode(model.node())
Пример #3
0
    def load_layer(self, layer):
        layer_node = NodePath(layer.get("name"))
        static_tiles = NodePath("static")  # Static tiles to flatten
        flat_animated_tiles = NodePath("animated")  # Animated tiles to flatten
        dynamic_tiles = NodePath(
            "dynamic")  # All tiles unless otherwise specified (don't flatten)
        tile_groups = {}
        # should we flatten this layer
        store_data = flatten = False
        properties = layer.find("properties")
        if properties:
            for property in properties:
                if property.get("name") == "flatten":
                    flatten = True
                if property.get("name") == "store_data":
                    store_data = True
        # build all tiles in data as a grid of cards
        data = layer.find("data").text
        data = data.replace('\n', '')
        data = data.split(",")
        collumns = int(layer.get("width"))
        rows = int(layer.get("height"))
        self.size = [collumns, rows]
        for y in range(rows):
            for x in range(collumns):
                id = int(data[(y * collumns) + (x % collumns)])
                data[(y * collumns) + (x % collumns)] = id
                if id > 0:
                    tile = NodePath("tile")
                    self.get_tile(id).copy_to(tile)
                    if flatten:
                        if tile.find("**/+SequenceNode"):
                            tile.reparent_to(flat_animated_tiles)
                        else:
                            tile.reparent_to(static_tiles)
                    else:
                        tile.reparent_to(layer_node)
                    tile.set_pos(x, -y, 0)

        if flatten:
            if static_tiles.get_num_children() > 0:
                clear_all_tags(static_tiles)
                static_tiles.flatten_strong()
            if flat_animated_tiles.get_num_children() > 0:
                clear_all_tags(flat_animated_tiles)
                flat_animated_tiles = self.flatten_animated_tiles(
                    flat_animated_tiles)
            for t in (static_tiles, flat_animated_tiles):
                t.reparent_to(layer_node)

        if store_data:
            layer_node.set_python_tag("data", data)
        self.append_layer(layer_node, properties)
Пример #4
0
    def initBodyShader(self):
        rig = NodePath('rig')
        buffer = base.win.makeCubeMap('env', 64, rig)
        rig.reparentTo(self.model)

        lens = rig.find('**/+Camera').node().getLens()
        lens.setNearFar(30, 1000)

        ts = TextureStage('env')
        self.model.setTexGen(ts, TexGenAttrib.MWorldCubeMap)
        self.model.setTexture(buffer.getTexture())

        self.refreshBodyShader()
Пример #5
0
    def handleNode(self, dgi, target=None):
        if target is None:
            return
        numNodes = dgi.getUint16()
        for _ in xrange(numNodes):
            code = DNAUtil.dgiExtractString8(dgi)
            file = DNAUtil.dgiExtractString8(dgi)
            node = DNAUtil.dgiExtractString8(dgi)
            np = NodePath(loader.jazzModel(file))
            if node:
                newNode = np.find('**/' + node).copyTo(NodePath())
                np.removeNode()
                np = newNode
            np.setTag('DNACode', code)
            np.setTag('DNARoot', node)
            target(np, code)

        return
Пример #6
0
class PopupMenu(DirectObject):
    '''
  A class to create a popup or context menu.
  Features :
    [1] it's destroyed by pressing ESCAPE, or LMB/RMB click outside of it
    [2] menu item's command is executed by pressing ENTER/RETURN or SPACE when
        it's hilighted
    [3] you can use arrow UP/DOWN to navigate
    [4] separator lines
    [5] menu item image
    [6] menu item hotkey
        If there are more than 1 item using the same hotkey,
        those items will be hilighted in cycle when the hotkey is pressed.
    [7] shortcut key text at the right side of menu item
    [8] multiple lines item text
    [9] menu item can have sub menus
    [10] it's offscreen-proof, try to put your pointer next to screen edge or corner
        before creating it
  '''
    grayImages = {}  # storage of grayed images,

    # so the same image will be converted to grayscale only once

    def __init__(self,
                 items,
                 parent=None,
                 buttonThrower=None,
                 onDestroy=None,
                 font=None,
                 baselineOffset=.0,
                 scale=.05,
                 itemHeight=1.,
                 leftPad=.0,
                 separatorHeight=.5,
                 underscoreThickness=1,
                 BGColor=(0, 0, 0, .7),
                 BGBorderColor=(1, .85, .4, 1),
                 separatorColor=(1, 1, 1, 1),
                 frameColorHover=(1, .85, .4, 1),
                 frameColorPress=(0, 1, 0, 1),
                 textColorReady=(1, 1, 1, 1),
                 textColorHover=(0, 0, 0, 1),
                 textColorPress=(0, 0, 0, 1),
                 textColorDisabled=(.5, .5, .5, 1),
                 minZ=None,
                 useMouseZ=True):
        '''
      items : a collection of menu items
         Item format :
            ( 'Item text', 'path/to/image', command )
                        OR
            ( 'Item text', 'path/to/image', command, arg1,arg2,.... )
         If you don't want to use an image, pass 0.

         To create disabled item, pass 0 for the command :
            ( 'Item text', 'path/to/image', 0 )
         so, you can easily switch between enabled or disabled :
            ( 'Item text', 'path/to/image', command if commandEnabled else 0 )
                        OR
            ( 'Item text', 'path/to/image', (0,command)[commandEnabled] )

         To create submenu, pass a sequence of submenu items for the command.
         To create disabled submenu, pass an empty sequence for the command.

         To enable hotkey, insert an underscore before the character,
         e.g. hotkey of 'Item te_xt' is 'x' key.

         To add shortcut key text at the right side of the item, append it at the end of
         the item text, separated by "more than" sign, e.g. 'Item text>Ctrl-T'.

         To insert separator line, pass 0 for the whole item.


      parent : where to attach the menu, defaults to aspect2d

      buttonThrower : button thrower whose thrown events are blocked temporarily
                      when the menu is displayed. If not given, the default
                      button thrower is used

      onDestroy : user function which will be called after the menu is fully destroyed
      
      font           : text font
      baselineOffset : text's baseline Z offset

      scale       : text scale
      itemHeight  : spacing between items, defaults to 1
      leftPad     : blank space width before text
      separatorHeight : separator line height, relative to itemHeight

      underscoreThickness : underscore line thickness

      BGColor, BGBorderColor, separatorColor, frameColorHover, frameColorPress,
      textColorReady, textColorHover, textColorPress, textColorDisabled
      are some of the menu components' color

      minZ : minimum Z position to restrain menu's bottom from going offscreen (-1..1).
             If it's None, it will be set a little above the screen's bottom.
      '''
        self.parent = parent if parent else aspect2d
        self.onDestroy = onDestroy
        self.BT = buttonThrower if buttonThrower else base.buttonThrowers[
            0].node()
        self.menu = NodePath('menu-%s' % id(self))
        self.parentMenu = None
        self.submenu = None
        self.BTprefix = self.menu.getName() + '>'
        self.submenuCreationTaskName = 'createSubMenu-' + self.BTprefix
        self.submenuRemovalTaskName = 'removeSubMenu-' + self.BTprefix
        self.font = font if font else TextNode.getDefaultFont()
        self.baselineOffset = baselineOffset
        if isinstance(scale, (float, int)):
            scale = (scale, 1.0, scale)
        self.scale = scale
        self.itemHeight = itemHeight
        self.leftPad = leftPad
        self.separatorHeight = separatorHeight
        self.underscoreThickness = underscoreThickness
        self.BGColor = BGColor
        self.BGBorderColor = BGBorderColor
        self.separatorColor = separatorColor
        self.frameColorHover = frameColorHover
        self.frameColorPress = frameColorPress
        self.textColorReady = textColorReady
        self.textColorHover = textColorHover
        self.textColorPress = textColorPress
        self.textColorDisabled = textColorDisabled
        self.minZ = minZ
        self.mpos = Point2(base.mouseWatcherNode.getMouse())

        self.itemCommand = []
        self.hotkeys = {}
        self.numItems = 0
        self.sel = -1
        self.selByKey = False

        bgPad = self.bgPad = .0125
        texMargin = self.font.getTextureMargin() * self.scale[0] * .25
        b = DirectButton(parent=NodePath(''),
                         text='^|g_',
                         text_font=self.font,
                         scale=self.scale)
        fr = b.node().getFrame()
        b.getParent().removeNode()
        baselineToCenter = (fr[2] + fr[3]) * self.scale[0]
        LH = (fr[3] - fr[2]) * self.itemHeight * self.scale[2]
        imageHalfHeight = .5 * (fr[3] - fr[2]) * self.itemHeight * .85
        arrowHalfHeight = .5 * (fr[3] - fr[2]) * self.itemHeight * .5
        baselineToTop = (fr[3] * self.itemHeight * self.scale[2] /
                         LH) / (1. + self.baselineOffset)
        baselineToBot = LH / self.scale[2] - baselineToTop
        itemZcenter = (baselineToTop - baselineToBot) * .5
        separatorHalfHeight = .5 * separatorHeight * LH
        LSseparator = LineSegs()
        LSseparator.setColor(.5, .5, .5, .2)

        arrowVtx = [
            (0, itemZcenter),
            (-2 * arrowHalfHeight, itemZcenter + arrowHalfHeight),
            (-arrowHalfHeight, itemZcenter),
            (-2 * arrowHalfHeight, itemZcenter - arrowHalfHeight),
        ]
        tri = Triangulator()
        vdata = GeomVertexData('trig', GeomVertexFormat.getV3(), Geom.UHStatic)
        vwriter = GeomVertexWriter(vdata, 'vertex')
        for x, z in arrowVtx:
            vi = tri.addVertex(x, z)
            vwriter.addData3f(x, 0, z)
            tri.addPolygonVertex(vi)
        tri.triangulate()
        prim = GeomTriangles(Geom.UHStatic)
        for i in range(tri.getNumTriangles()):
            prim.addVertices(tri.getTriangleV0(i), tri.getTriangleV1(i),
                             tri.getTriangleV2(i))
            prim.closePrimitive()
        geom = Geom(vdata)
        geom.addPrimitive(prim)
        geomNode = GeomNode('arrow')
        geomNode.addGeom(geom)
        realArrow = NodePath(geomNode)
        z = -baselineToTop * self.scale[2] - bgPad
        maxWidth = .1 / self.scale[0]
        shortcutTextMaxWidth = 0
        anyImage = False
        anyArrow = False
        anyShortcut = False
        arrows = []
        shortcutTexts = []
        loadPrcFileData('', 'text-flatten 0')
        for item in items:
            if item:
                t, imgPath, f = item[:3]
                haveSubmenu = type(f) in SEQUENCE_TYPES
                anyArrow |= haveSubmenu
                anyImage |= isinstance(imgPath, bool) or bool(imgPath)
                disabled = not len(f) if haveSubmenu else not callable(f)
                args = item[3:]
                underlinePos = t.find('_')
                t = t.replace('_', '')
                shortcutSepPos = t.find('>')
                if shortcutSepPos > -1:
                    if haveSubmenu:
                        print(
                            "\nA SHORTCUT KEY POINTING TO A SUBMENU IS NON-SENSE, DON'T YOU AGREE ?"
                        )
                    else:
                        shortcutText = NodePath(
                            OnscreenText(
                                parent=self.menu,
                                text=t[shortcutSepPos + 1:],
                                font=self.font,
                                scale=1,
                                fg=(1, 1, 1, 1),
                                align=TextNode.ARight,
                            ))
                        shortcutTextMaxWidth = max(
                            shortcutTextMaxWidth,
                            abs(shortcutText.getTightBounds()[0][0]))
                        anyShortcut = True
                    t = t[:shortcutSepPos]
                else:
                    shortcutText = ''
                EoLcount = t.count('\n')
                arrowZpos = -self.font.getLineHeight() * EoLcount * .5
                if disabled:
                    b = NodePath(
                        OnscreenText(
                            parent=self.menu,
                            text=t,
                            font=self.font,
                            scale=1,
                            fg=textColorDisabled,
                            align=TextNode.ALeft,
                        ))
                    # don't pass the scale and position to OnscreenText constructor,
                    # to maintain correctness between the OnscreenText and DirectButton items
                    # due to the new text generation implementation
                    b.setScale(self.scale)
                    b.setZ(z)
                    maxWidth = max(maxWidth,
                                   b.getTightBounds()[1][0] / self.scale[0])
                    if shortcutText:
                        shortcutText.reparentTo(b)
                        shortcutText.setColor(Vec4(*textColorDisabled), 1)
                        shortcutText.setZ(arrowZpos)
                        shortcutTexts.append(shortcutText)
                else:
                    b = DirectButton(
                        parent=self.menu,
                        text=t,
                        text_font=self.font,
                        scale=self.scale,
                        pos=(0, 0, z),
                        text_fg=textColorReady,
                        # text color when mouse over
                        text2_fg=textColorHover,
                        # text color when pressed
                        text1_fg=textColorHover
                        if haveSubmenu else textColorPress,
                        # framecolor when pressed
                        frameColor=frameColorHover
                        if haveSubmenu else frameColorPress,
                        commandButtons=[DGG.LMB, DGG.RMB],
                        command=(lambda: 0)
                        if haveSubmenu else self.__runCommand,
                        extraArgs=[] if haveSubmenu else [f, args],
                        text_align=TextNode.ALeft,
                        relief=DGG.FLAT,
                        rolloverSound=0,
                        clickSound=0,
                        pressEffect=0)
                    b.stateNodePath[2].setColor(
                        *frameColorHover)  # framecolor when mouse over
                    b.stateNodePath[0].setColor(0, 0, 0,
                                                0)  # framecolor when ready
                    bframe = Vec4(b.node().getFrame())
                    if EoLcount:
                        bframe.setZ(EoLcount * 10)
                        b['frameSize'] = bframe
                    maxWidth = max(maxWidth, bframe[1])
                    if shortcutText:
                        for snpi, col in ((0, textColorReady),
                                          (1, textColorPress),
                                          (2, textColorHover)):
                            sct = shortcutText.copyTo(b.stateNodePath[snpi],
                                                      sort=10)
                            sct.setColor(Vec4(*col), 1)
                            sct.setZ(arrowZpos)
                            shortcutTexts.append(sct)
                        shortcutText.removeNode()
                if isinstance(imgPath, bool):
                    if imgPath:
                        if disabled:
                            fg = textColorDisabled
                        else:
                            fg = textColorReady
                        tick = NodePath(
                            OnscreenText(
                                parent=b,
                                text=u"\u2714",
                                font=self.font,
                                scale=1,
                                fg=fg,
                                align=TextNode.ALeft,
                            ))
                        tick.setX(-2 * imageHalfHeight - leftPad)
                elif imgPath:
                    img = loader.loadTexture(imgPath, okMissing=True)
                    if img is not None:
                        if disabled:
                            if imgPath in PopupMenu.grayImages:
                                img = PopupMenu.grayImages[imgPath]
                            else:
                                pnm = PNMImage()
                                img.store(pnm)
                                pnm.makeGrayscale(.2, .2, .2)
                                img = Texture()
                                img.load(pnm)
                                PopupMenu.grayImages[imgPath] = img
                        img.setMinfilter(Texture.FTLinearMipmapLinear)
                        img.setWrapU(Texture.WMClamp)
                        img.setWrapV(Texture.WMClamp)
                        CM = CardMaker('')
                        CM.setFrame(-2 * imageHalfHeight - leftPad, -leftPad,
                                    itemZcenter - imageHalfHeight,
                                    itemZcenter + imageHalfHeight)
                        imgCard = b.attachNewNode(CM.generate())
                        imgCard.setTexture(img)
                if underlinePos > -1:
                    oneLineText = t[:underlinePos + 1]
                    oneLineText = oneLineText[oneLineText.rfind('\n') + 1:]
                    tn = TextNode('')
                    tn.setFont(self.font)
                    tn.setText(oneLineText)
                    tnp = NodePath(tn.getInternalGeom())
                    underlineXend = tnp.getTightBounds()[1][0]
                    tnp.removeNode()
                    tn.setText(t[underlinePos])
                    tnp = NodePath(tn.getInternalGeom())
                    b3 = tnp.getTightBounds()
                    underlineXstart = underlineXend - (b3[1] - b3[0])[0]
                    tnp.removeNode()
                    underlineZpos = -.7 * baselineToBot - self.font.getLineHeight(
                    ) * t[:underlinePos].count('\n')
                    LSunder = LineSegs()
                    LSunder.setThickness(underscoreThickness)
                    LSunder.moveTo(underlineXstart + texMargin, 0,
                                   underlineZpos)
                    LSunder.drawTo(underlineXend - texMargin, 0, underlineZpos)
                    if disabled:
                        underline = b.attachNewNode(LSunder.create())
                        underline.setColor(Vec4(*textColorDisabled), 1)
                    else:
                        underline = b.stateNodePath[0].attachNewNode(
                            LSunder.create())
                        underline.setColor(Vec4(*textColorReady), 1)
                        underline.copyTo(b.stateNodePath[1], 10).setColor(
                            Vec4(*textColorHover
                                 if haveSubmenu else textColorPress), 1)
                        underline.copyTo(b.stateNodePath[2],
                                         10).setColor(Vec4(*textColorHover), 1)
                        hotkey = t[underlinePos].lower()
                        if hotkey in self.hotkeys:
                            self.hotkeys[hotkey].append(self.numItems)
                        else:
                            self.hotkeys[hotkey] = [self.numItems]
                            self.accept(self.BTprefix + hotkey,
                                        self.__processHotkey, [hotkey])
                            self.accept(self.BTprefix + 'alt-' + hotkey,
                                        self.__processHotkey, [hotkey])
                if haveSubmenu:
                    if disabled:
                        arrow = realArrow.instanceUnderNode(b, '')
                        arrow.setColor(Vec4(*textColorDisabled), 1)
                        arrow.setZ(arrowZpos)
                    else:
                        arrow = realArrow.instanceUnderNode(
                            b.stateNodePath[0], 'r')
                        arrow.setColor(Vec4(*textColorReady), 1)
                        arrow.setZ(arrowZpos)
                        arrPress = realArrow.instanceUnderNode(
                            b.stateNodePath[1], 'p')
                        arrPress.setColor(Vec4(*textColorHover), 1)
                        arrPress.setZ(arrowZpos)
                        arrHover = realArrow.instanceUnderNode(
                            b.stateNodePath[2], 'h')
                        arrHover.setColor(Vec4(*textColorHover), 1)
                        arrHover.setZ(arrowZpos)
                        # weird, if sort order is 0, it's obscured by the frame
                        for a in (arrPress, arrHover):
                            a.reparentTo(a.getParent(), sort=10)
                if not disabled:
                    extraArgs = [self.numItems, f if haveSubmenu else 0]
                    self.accept(DGG.ENTER + b.guiId, self.__hoverOnItem,
                                extraArgs)
                    self.accept(DGG.EXIT + b.guiId, self.__offItem)
                    #~ self.itemCommand.append((None,0) if haveSubmenu else (f,args))
                    self.itemCommand.append((f, args))
                    if self.numItems == 0:
                        self.firstButtonIdx = int(b.guiId[2:])
                    self.numItems += 1
                z -= LH + self.font.getLineHeight() * self.scale[2] * EoLcount
            else:  # SEPARATOR LINE
                z += LH - separatorHalfHeight - baselineToBot * self.scale[2]
                LSseparator.moveTo(0, 0, z)
                LSseparator.drawTo(self.scale[0] * .5, 0, z)
                LSseparator.drawTo(self.scale[0], 0, z)
                z -= separatorHalfHeight + baselineToTop * self.scale[2]
        maxWidth += 7 * arrowHalfHeight * (
            anyArrow or anyShortcut) + .2 + shortcutTextMaxWidth
        arrowXpos = maxWidth - arrowHalfHeight
        realArrow.setX(arrowXpos)
        if anyImage:
            leftPad += 2 * imageHalfHeight + leftPad
        for sct in shortcutTexts:
            sct.setX(maxWidth - 2 * (arrowHalfHeight * anyArrow + .2))
        for c in asList(self.menu.findAllMatches('**/DirectButton*')):
            numLines = c.node().getFrame()[2]
            c.node().setFrame(
                Vec4(
                    -leftPad, maxWidth, -baselineToBot -
                    (numLines * .1 * self.itemHeight if numLines >= 10 else 0),
                    baselineToTop))
        loadPrcFileData('', 'text-flatten 1')

        try:
            minZ = self.menu.getChild(0).getRelativePoint(
                b, Point3(0, 0,
                          b.node().getFrame()[2]))[2]
        except:
            minZ = self.menu.getChild(0).getRelativePoint(
                self.menu, Point3(
                    0, 0,
                    b.getTightBounds()[0][2]))[2] - baselineToBot * .5
        try:
            top = self.menu.getChild(0).node().getFrame()[3]
        except:
            top = self.menu.getChild(0).getZ() + baselineToTop
        l, r, b, t = -leftPad - bgPad / self.scale[
            0], maxWidth + bgPad / self.scale[0], minZ - bgPad / self.scale[
                2], top + bgPad / self.scale[2]
        menuBG = DirectFrame(parent=self.menu.getChild(0),
                             frameSize=(l, r, b, t),
                             frameColor=BGColor,
                             state=DGG.NORMAL,
                             suppressMouse=1)
        menuBorder = self.menu.getChild(0).attachNewNode('border')
        borderVtx = (
            (l, 0, b),
            (l, 0, .5 * (b + t)),
            (l, 0, t),
            (.5 * (l + r), 0, t),
            (r, 0, t),
            (r, 0, .5 * (b + t)),
            (r, 0, b),
            (.5 * (l + r), 0, b),
            (l, 0, b),
        )
        LSborderBG = LineSegs()
        LSborderBG.setThickness(4)
        LSborderBG.setColor(0, 0, 0, .7)
        LSborderBG.moveTo(*(borderVtx[0]))
        for v in borderVtx[1:]:
            LSborderBG.drawTo(*v)
        # fills the gap at corners
        for v in range(0, 7, 2):
            LSborderBG.moveTo(*(borderVtx[v]))
        menuBorder.attachNewNode(LSborderBG.create())
        LSborder = LineSegs()
        LSborder.setThickness(2)
        LSborder.setColor(*BGBorderColor)
        LSborder.moveTo(*(borderVtx[0]))
        for v in borderVtx[1:]:
            LSborder.drawTo(*v)
        menuBorder.attachNewNode(LSborder.create())
        for v in range(1, 8, 2):
            LSborderBG.setVertexColor(v, Vec4(0, 0, 0, .1))
            LSborder.setVertexColor(v, Vec4(.3, .3, .3, .5))
        menuBorderB3 = menuBorder.getTightBounds()
        menuBorderDims = menuBorderB3[1] - menuBorderB3[0]
        menuBG.wrtReparentTo(self.menu, sort=-1)
        self.menu.reparentTo(self.parent)
        x = -menuBorderB3[0][0] * self.scale[0]
        for c in asList(self.menu.getChildren()):
            c.setX(x)
        self.maxWidth = maxWidth = menuBorderDims[0]
        self.height = menuBorderDims[2]
        maxWidthR2D = maxWidth * self.menu.getChild(0).getSx(render2d)
        separatorLines = self.menu.attachNewNode(LSseparator.create(), 10)
        separatorLines.setSx(maxWidth)
        for v in range(1, LSseparator.getNumVertices(), 3):
            LSseparator.setVertexColor(v, Vec4(*separatorColor))
        x = clamp(-.98, .98 - maxWidthR2D, self.mpos[0] - maxWidthR2D * .5)
        minZ = (-.98 if self.minZ is None else self.minZ)
        z = clamp(
            minZ +
            menuBorderDims[2] * self.scale[2] * self.parent.getSz(render2d),
            .98, self.mpos[1] if useMouseZ else -1000)
        self.menu.setPos(render2d, x, 0, z)
        self.menu.setTransparency(1)

        self.origBTprefix = self.BT.getPrefix()
        self.BT.setPrefix(self.BTprefix)
        self.accept(self.BTprefix + 'escape', self.destroy)
        for e in ('mouse1', 'mouse3'):
            self.accept(self.BTprefix + e, self.destroy, [True])
        self.accept(self.BTprefix + 'arrow_down', self.__nextItem)
        self.accept(self.BTprefix + 'arrow_down-repeat', self.__nextItem)
        self.accept(self.BTprefix + 'arrow_up', self.__prevItem)
        self.accept(self.BTprefix + 'arrow_up-repeat', self.__prevItem)
        self.accept(self.BTprefix + 'enter', self.__runSelItemCommand)
        self.accept(self.BTprefix + 'space', self.__runSelItemCommand)

    def __offItem(self, crap):
        self.sel = -1
        self.__cancelSubmenuCreation()

    def __hoverOnItem(self, idx, menu, crap):
        self.sel = idx
        self.__cancelSubmenuCreation()
        if self.BT.getPrefix()==self.BTprefix or \
             (self.submenu and self.submenuIdx==idx):
            self.__cancelSubmenuRemoval()
        if menu:
            if not (self.submenu and self.submenuIdx == idx):
                #~ if self.selByKey:
                #~ self.selByKey=False
                #~ self.__createSubmenu(idx,menu)
                #~ else:
                taskMgr.doMethodLater(.3,
                                      self.__createSubmenu,
                                      self.submenuCreationTaskName,
                                      extraArgs=[idx, menu])
        else:
            taskMgr.doMethodLater(.5,
                                  self.__removeSubmenu,
                                  self.submenuRemovalTaskName,
                                  extraArgs=[])

    def __cancelSubmenuCreation(self):
        taskMgr.removeTasksMatching('createSubMenu-*')

    def __createSubmenu(self, idx, menu):
        self.__cancelSubmenuCreation()
        self.__removeSubmenu()
        self.submenu = PopupMenu(items=menu,
                                 parent=self.parent,
                                 buttonThrower=self.BT,
                                 font=self.font,
                                 baselineOffset=self.baselineOffset,
                                 scale=self.scale,
                                 itemHeight=self.itemHeight,
                                 leftPad=self.leftPad,
                                 separatorHeight=self.separatorHeight,
                                 underscoreThickness=self.underscoreThickness,
                                 BGColor=self.BGColor,
                                 BGBorderColor=self.BGBorderColor,
                                 separatorColor=self.separatorColor,
                                 frameColorHover=self.frameColorHover,
                                 frameColorPress=self.frameColorPress,
                                 textColorReady=self.textColorReady,
                                 textColorHover=self.textColorHover,
                                 textColorPress=self.textColorPress,
                                 textColorDisabled=self.textColorDisabled,
                                 minZ=self.minZ,
                                 useMouseZ=False)
        self.submenuIdx = idx
        self.submenu.parentMenu = self
        if self.menu.getBinName():
            self.submenu.menu.setBin(self.menu.getBinName(),
                                     self.menu.getBinDrawOrder() + 1)
        sb3 = self.submenu.menu.getTightBounds()
        sb = sb3[1] - sb3[0]
        b3 = self.menu.getTightBounds()
        x = b3[1][0]
        if render2d.getRelativePoint(self.parent, Point3(x + sb[0], 0,
                                                         0))[0] > .98:
            x = b3[0][0] - sb[0]
        if render2d.getRelativePoint(self.parent, Point3(x, 0, 0))[0] < -.98:
            x = self.parent.getRelativePoint(render2d, Point3(-.98, 0, 0))[0]
        item = self.menu.find('**/*-pg%s' % (self.firstButtonIdx + idx))
        z = self.parent.getRelativePoint(
            item, Point3(0, 0,
                         item.node().getFrame()[3]))[2] + self.bgPad
        self.submenu.menu.setPos(x, 0, max(z, self.submenu.menu.getZ()))


#       self.submenu.menu.setPos(x,0,z)

    def __nextItem(self):
        if self.numItems:
            self.sel = clamp(0, self.numItems - 1, self.sel + 1)
            self.__putPointerAtItem()
            self.selByKey = True

    def __prevItem(self):
        if self.numItems:
            self.sel = clamp(0, self.numItems - 1,
                             (self.sel -
                              1) if self.sel > -1 else self.numItems - 1)
            self.__putPointerAtItem()
            self.selByKey = True

    def __putPointerAtItem(self):
        item = self.menu.find('**/*-pg%s' % (self.firstButtonIdx + self.sel))
        fr = item.node().getFrame()
        c = Point3(.5 * (fr[0] + fr[1]), 0, .5 * (fr[2] + fr[3]))
        cR2D = render2d.getRelativePoint(item, c)
        x, y = int(base.win.getXSize() * .5 * (cR2D[0] + 1)), int(
            base.win.getYSize() * .5 * (-cR2D[2] + 1))
        if '__origmovePointer' in base.win.DtoolClassDict:
            base.win.DtoolClassDict['__origmovePointer'](base.win, 0, x, y)
        else:
            base.win.movePointer(0, x, y)

    def __processHotkey(self, hotkey):
        itemsIdx = self.hotkeys[hotkey]
        if len(itemsIdx) == 1 and type(
                self.itemCommand[itemsIdx[0]][0]) not in SEQUENCE_TYPES:
            self.__runCommand(*self.itemCommand[itemsIdx[0]])
        else:
            if self.sel in itemsIdx:
                idx = itemsIdx.index(self.sel) + 1
                idx %= len(itemsIdx)
                self.sel = itemsIdx[idx]
            else:
                self.sel = itemsIdx[0]
            self.selByKey = True
            # if it's already there, putting the pointer doesn't trigger the 'enter'
            # event, so just bypass it
            if not (self.submenu and self.submenuIdx==self.sel) and\
                 type(self.itemCommand[itemsIdx[0]][0]) in SEQUENCE_TYPES:
                self.__createSubmenu(self.sel,
                                     self.itemCommand[itemsIdx[0]][0])
            self.__putPointerAtItem()

    def __doRunCommand(self, f, args):
        self.destroy(delParents=True)
        f(*args)

    def __runCommand(self, f, args):
        if callable(f):
            # must be done at next frame, so shortcut key event won't bleed to the scene
            taskMgr.doMethodLater(.01,
                                  self.__doRunCommand,
                                  'run menu command',
                                  extraArgs=[f, args])

    def __runSelItemCommand(self):
        if self.sel == -1: return
        self.__runCommand(*self.itemCommand[self.sel])

    def __cancelSubmenuRemoval(self):
        taskMgr.removeTasksMatching('removeSubMenu-*')

    def __removeSubmenu(self):
        self.__cancelSubmenuRemoval()
        if self.submenu:
            self.submenu.destroy()

    def destroy(self, delParents=False):
        self.__cancelSubmenuCreation()
        self.__removeSubmenu()
        self.subMenu = None
        self.ignoreAll()
        self.menu.removeNode()
        #       if self.origBTprefix.find('menu-')==-1:
        #          taskMgr.step()
        self.BT.setPrefix(self.origBTprefix)
        messenger.send(self.BTprefix + 'destroyed')
        if delParents and self.parentMenu:
            parent = self.parentMenu
            while parent.parentMenu:
                parent = parent.parentMenu
            parent.destroy()
        if self.parentMenu:
            self.parentMenu.submenuIdx = None
            self.parentMenu = None
        if callable(self.onDestroy):
            self.onDestroy()
class RigidBodyRig:

    def __init__(self):
        self.root = NodePath('root')

    def createColliders(self, pose_rig):
        self.colliders = list(create_colliders(self.root, pose_rig, joints_config))

    def createConstraints(self, offset_scale):
        self.constraints = list(create_constraints(self.root, get_joint_pairs(self.root, joints_config), offset_scale))

    def clearMasses(self):
        [collider.node().setMass(0) for collider in self.colliders]

    def attachCubes(self, loader):
        for collider in self.colliders:
            for i in range(collider.node().getNumShapes()):
                shape = collider.node().getShape(i)
                mat = collider.node().getShapeMat(i)
                scale = shape.getHalfExtentsWithMargin()

                transform = TransformState.makeMat(mat)

                cube = loader.loadModel("cube.egg")
                cube.setTransform(transform)
                cube.setScale(scale)
                cube.reparentTo(collider)

    def setScale(self, *scale):
        self.root.setScale(*scale)

    def setPos(self, *pos):
        self.root.setPos(*pos)

    def babble(self):
        F_all = []

        for collider in self.colliders:
            collider_name = collider.getName()
            if collider_name == "Hips":
                continue

            F = random.uniform(-1.0, 1.0) * joints_config[collider_name].get("F_max", 4000.0)
            F_all.append(F)

            r = Vec3(*joints_config[collider_name].get("axis", (1, 0, 0)))
            r_world = collider.getQuat(self.root).xform(r)
            T = r_world * F

            collider.node().applyTorqueImpulse(T)

        return np.array(F_all)

    def apply_forces(self, F_all):
        i = 0
        for collider in self.colliders:
            if collider.getName() == "Hips":
                continue

            F = F_all[i]

            r = Vec3(1, 0, 0)
            r_world = collider.getQuat(self.root).xform(r)
            T = r_world * F

            collider.node().applyTorqueImpulse(T)
            i += 1

    def compareTo(self, target):
        positions = self.getJointPositions()
        rotations = self.getJointRotations()

        target_positions = target.getJointPositions()
        target_rotations = target.getJointRotations()

        err_pos = np.abs((positions - target_positions) / 200.0).sum()
        err_hpr = np.abs((rotations - target_rotations) / 180.0).sum()

        return err_pos + err_hpr

    def matchPose(self, pose_rig):
        for node, parent in pose_rig.exposed_joints:
            if node.getName() not in joints_config:
                continue

            joint_config = joints_config[node.getName()]
            if 'joints' not in joint_config:
                continue

            joints = joint_config['joints']
            if len(joints) == 0:
                continue

            box_np = self.root.find(node.getName())

            if len(joints) > 1:
                pos = node.getPos(pose_rig.actor)
                hpr = node.getHpr(pose_rig.actor)
                box_np.setPosHpr(self.root, pos, hpr)
            else:
                joint = joints.keys()[0]
                child_node, child_parent = next((child_node, child_parent) for child_node, child_parent in pose_rig.exposed_joints if child_node.getName() == joint)
                box_np.setPos(child_parent, child_node.getPos(child_parent) / 2.0)

                quat = Quat()
                lookAt(quat, child_node.getPos(child_parent), Vec3.up())
                box_np.setQuat(child_parent, quat)

            box_np.node().clearForces()

    def clearForces(self):
        for collider in self.colliders:
            collider.node().clearForces()

    def setPos(self, *pos):
        self.root.setPos(*pos)

    def reparentTo(self, other):
        self.root.reparentTo(other)

    def setCollideMask(self, mask):
        for child in self.root.getChildren():
            child.setCollideMask(mask)

    def attachRigidBodies(self, world):
        for collider in self.colliders:
            world.attachRigidBody(collider.node())

    def attachConstraints(self, world):
        for constraint in self.constraints:
            world.attachConstraint(constraint, linked_collision=True)

    def getJointPositions(self):
        return np.concatenate([collider.getPos(self.root) for collider in self.colliders]) # TODO: is root necessary?

    def getJointRotations(self):
        return np.concatenate([collider.getHpr(self.root) for collider in self.colliders]) # TODO: is root necessary?

    def getLinearVelocities(self):
        return np.concatenate([collider.node().getLinearVelocity() for collider in self.colliders])

    def getAngularVelocities(self):
        return get_angle_vec(np.concatenate([collider.node().getAngularVelocity() for collider in self.colliders]))
Пример #8
0
class Client(DirectObject):
    def __init__(self, parent, player, player_id, type="ContGame", game_id = TEST_GAME_ID ):
        self.parent = parent
        self.player = player
        self.player_id = player_id
        self.game_id = game_id
        self.type = type
        
        # Flags
        self._game_initialized = False
        # This handles message queue - we will process messages in sync one by one
        self._message_in_process = False
        # This handles interface interactions - we will not allow interaction if current animation is not done
        self._anim_in_process = False 
        
        self.fsm = ClientFSM(self, 'ClientFSM')
        self.rRegion = RocketRegion.make('squad_select', base.win)
        self.rContext = self.rRegion.getContext()
        ih = RocketInputHandler()
        base.mouseWatcher.attachNewNode(ih)
        self.rRegion.setInputHandler(ih)
        # Initialize game mode (network)
        base.accept('n', render.setShaderAuto)
        base.accept('m', render.setShaderOff)
        
        self.net = Net(self)
        self.net.startNet()
        
        ClientMsg.getMyGames()
        
        if type == "ContGame":
            ClientMsg.enterGame( game_id )
            taskMgr.doMethodLater(1, ClientMsg.forceFirstTurn, 'ForceTurn', extraArgs = [])   
        elif type == 'NewGame':
            ClientMsg.startNewGame('base2', 1000, [17, 19])
            
            
    def newGameStarted(self, game_id):
        print "aaaaaaaaaa", game_id
        ClientMsg.enterGame( game_id )
        ClientMsg.forceFirstTurn()
            
        
    def getPlayerName(self, player_id):
        for p in self.players:
            if p['id'] == player_id:
                return p['name']
            
    def deselectUnit(self):
        self.movement.deleteUnitAvailMove()
        self.sgm.hideVisibleEnemies()
        self.interface.clearUnitData()
        
        if self.sel_unit_id != None:
            self.sgm.unit_np_dict[self.sel_unit_id].clearAllFlags()
        self.sel_unit_id = None
    
    def selectUnit(self, unit_id):
        if self._anim_in_process == True:
            return
        
        if not self.units.has_key(unit_id):
            return
        
        if self.sel_unit_id != unit_id:
            self.deselectUnit()
            self.sel_unit_id = unit_id
            self.interface.processUnitData(unit_id)
            self.interface.printUnitData(unit_id)
            self.interface.refreshUnitInfo(unit_id)
            # If it is our turn, display available move tiles
            if self.player == self.turn_player:
                self.sgm.unit_np_dict[unit_id].setSelected()
                self.movement.calcUnitAvailMove(unit_id)
                self.sgm.showVisibleEnemies(unit_id)
            
    def selectNextUnit(self):
        if self.sel_unit_id == None:
            last = 0
        else:
            last = self.sel_unit_id
        
        d = {}
        for unit_id in self.units.iterkeys():
            if self.isThisMyUnit(unit_id):
                d[unit_id] = self.units[unit_id]
        
        l = sorted(d.iterkeys())
        if len(l) <= 1:
            return
        else:
            if l[-1] == last:
                new_unit_id = l[0]
            else:
                for i in l:
                    if i > last:
                        new_unit_id = i
                        break
            self.selectUnit(new_unit_id)
        
    def selectPrevUnit(self):
        if self.sel_unit_id == None:
            # TODO: ogs: Kaj fakat?
            last = 9999999
        else:
            last = self.sel_unit_id
            
        d = {}
        for unit_id in self.units.iterkeys():
            if self.isThisMyUnit(unit_id):
                d[unit_id] = self.units[unit_id]
        
        l = sorted(d.iterkeys())
        l.reverse()
        if len(l) <= 1:
            return
        else:
            if l[-1] == last:
                new_unit_id = l[0]
            else:
                for i in l:
                    if i < last:
                        new_unit_id = i
                        break
            self.selectUnit(new_unit_id)
    
    def refreshUnit(self, unit):
        if unit['alive'] == False:
            if self.sel_unit_id == unit['id']:
                self.sel_unit_id = None
            if self.sgm.unit_np_dict.has_key(unit['id']):
                self.sgm.hideUnit(unit['id'])
            if self.units.has_key(unit['id']):
                if self.isThisMyUnit(unit['id']):
                    self.inactive_units[unit['id']] = unit
                self.deleteUnit(unit['id'])
            self.level.removeUnitDict(unit)
        else:
            self.units[unit['id']] = unit
            self.level.removeUnitId(unit['id'])
            self.level.putUnitDict(unit)
    
    def deleteUnit(self, unit_id):
        self.level.removeUnitId(unit_id)
        self.units.pop(unit_id)
    
    def getUnitData(self, unit_id):
        if self.units.has_key(unit_id):
            return self.units[unit_id]
    
    def isThisMyUnit(self, unit_id):
        if self.units.has_key(unit_id):
            if self.units[unit_id]['owner_id'] == self.player_id:
                return True
            else:
                return False
        else:
            return False
        
    def isThisEnemyUnit(self, unit_id):
        if self.units.has_key(unit_id):
            if self.units[unit_id]['owner_id'] != self.player_id:
                return True
            else:
                return False
        else:
            return False
        
    def isUnitAlive(self, unit_id):
        return self.units[unit_id]['alive']
    
    def getCoordsByUnit(self, unit_id):
        if self.units.has_key(unit_id):
            unit = self.units[unit_id]
        return Point2(unit['pos'][0], unit['pos'][1])
    
    def getUnitByCoords(self, pos):
        for u in self.units.itervalues():
            if u['pos'][0] == pos.getX() and u['pos'][1] == pos.getY():
                return u['id']
        return None
    
    def beforeAnimHook(self):
        self._anim_in_process = True
        self.movement.deleteUnitAvailMove()
        self.sgm.hideVisibleEnemies()
        for u in self.sgm.unit_np_dict.itervalues():
            u.clearTargeted()
        self.movement.hovered_unit_id = None
            
    
    def afterAnimHook(self):     
        self._anim_in_process = False
        self._message_in_process = False
    
#========================================================================
# Client animation handler methods
    def handleMove(self, move_msg):
        move = self.buildMove(move_msg)
        s = Sequence(Func(self.beforeAnimHook), move, Func(self.afterAnimHook))
        s.start()
    
    def buildMove(self, move_msg):
        unit_id = move_msg[0]
        action_list = move_msg[1]
        
        pos = None
        heading = None
        unit_model = None
        
        s = Sequence()
        d = 0.0
        
        if self.units.has_key(unit_id):
            pos = Point3(utils.TILE_SIZE*(self.units[unit_id]['pos'][0] + 0.5), utils.TILE_SIZE*(self.units[unit_id]['pos'][1] + 0.5), utils.GROUND_LEVEL)
            heading = utils.getHeadingAngle(self.units[unit_id]['heading'])
            if self.sgm.unit_np_dict.has_key(unit_id):
                unit_model = self.sgm.unit_np_dict[unit_id]
        else:
            # This is the first time we see this unit, we have no record of it in client.units dict or sgm nodepath list and dict
            # First action we MUST receive here is 'spot', otherwise client will break as we dont have unit_model defined
            None
            
        for idx, action in enumerate(action_list):
            action_type = action[0]
            if action_type == "move":
                end_pos = Point3(utils.TILE_SIZE*(action[1][0] + 0.5), utils.TILE_SIZE*(action[1][1] + 0.5), utils.GROUND_LEVEL)
                i, duration, pos, heading = self.buildMoveAnim(unit_model, pos, end_pos, heading)
                d += duration
                s.append(i)
            elif action_type == "rotate":
                end_pos = Point3(utils.TILE_SIZE*(action[1][0] + 0.5), utils.TILE_SIZE*(action[1][1] + 0.5), utils.GROUND_LEVEL)
                i, duration, pos, heading = self.buildRotateAnim(unit_model, pos, end_pos, heading)
                d += duration
                s.append(i)
            elif action_type == "spot":
                spotted_unit = action[1]
                self.units[spotted_unit['id']] = spotted_unit
                # Check if we have this unit in our scene graph records
                if self.sgm.unit_np_dict.has_key(spotted_unit['id']):
                    spotted_unit_model = self.sgm.unit_np_dict[spotted_unit['id']]
                # This is the first time we see this unit, fill out starting variables for move and rotate actions
                else:
                    wpn_list = utils.getUnitWeapons(spotted_unit)
                    spotted_unit_model = self.sgm.loadUnit(spotted_unit['id'], wpn_list)
                
                # If this is our move message, means we spotted an enemy, and he will not be moving
                # If this is enemy move message, means we have spotted a moving enemy and we will set unit_model variable
                if self.isThisEnemyUnit(unit_id):
                    unit_model = spotted_unit_model
                    pos = Point3(utils.TILE_SIZE*(self.units[spotted_unit['id']]['pos'][0] + 0.5), 
                                 utils.TILE_SIZE*(self.units[spotted_unit['id']]['pos'][1] + 0.5),
                                 utils.GROUND_LEVEL
                                 )
                    heading = utils.getHeadingAngle(self.units[spotted_unit['id']]['heading'])
                    spotted_pos = pos
                    spotted_h = heading
                else:
                    spotted_pos = None
                    spotted_h = None
                i = self.buildSpotAnim(spotted_unit_model, spotted_pos, spotted_h)
                s.append(i)
            elif action_type == "vanish":
                vanish_unit_id = action[1]
                spotted_later = False
                for a in action_list[idx:]:
                    if a[0] == "spot":
                        spotted_later = True
                        break
                if spotted_later:
                    i = self.buildDetachAnim(vanish_unit_id)
                else:
                    i = self.buildDeleteAnim(vanish_unit_id)
                s.append(i)
            elif action_type == "overwatch":
                action_list = action[1]
                i = self.buildOverwatchAnim(action_list)
                s.append(i)
        if unit_model.fsm.state == 'Overwatch':
            #move = Sequence(unit_model.model.actorInterval('stand_up'), Func(unit_model.fsm.request, 'Walk'), s, Func(unit_model.fsm.request, 'Idle'))
            move = Sequence(unit_model.model.actorInterval('stand_up'), Func(unit_model.fsm.request, 'Walk'), s, Func(unit_model.fsm.request, 'Idle'))
        else:
            move = Sequence(Func(unit_model.fsm.request, 'Walk'), s, Func(unit_model.fsm.request, 'Idle'))
        return move
        
    def buildMoveAnim(self, unit_model, start_pos, end_pos, start_h):
        dummy_start = NodePath("dummy_start")
        dummy_end = NodePath("dummy_end")
        duration = 0.0
        p = None   
        dummy_start.setPos(start_pos)
        dummy_end.setPos(end_pos)
        dummy_start.lookAt(dummy_end) 
        end_h = dummy_start.getH(render)               
        # Model heading is different than movement heading, first create animation that turns model to his destination
        i_h = None
        if end_h != start_h:
            i_h = unit_model.model.quatInterval(0.2, hpr = Point3(end_h, 0, 0), startHpr = Point3(start_h, 0, 0))
        i = unit_model.node.posInterval(0.5, end_pos, start_pos)
        duration += 0.5
        if i_h:
            p = Parallel(i, i_h)
        else:
            p = i
        return p, duration, end_pos, end_h  
    
    def buildRotateAnim(self, unit_model, start_pos, end_pos, start_h, heading=None):
        if heading == None:
            dummy_start = NodePath("dummy_start")
            dummy_end = NodePath("dummy_end")
            dummy_start.setPos(start_pos)
            dummy_end.setPos(end_pos)
            dummy_start.lookAt(dummy_end)
            end_h = dummy_start.getH(render)
        else:
            end_h = utils.getHeadingAngle(heading)
        interval = unit_model.model.quatInterval(0.2, hpr = Point3(end_h, 0, 0), startHpr = Point3(start_h, 0, 0))
        duration = 0.2
        return interval, duration, start_pos, end_h          
    
    def buildSpotAnim(self, unit_model, pos, heading):
        return Sequence(Func(self.sgm.showUnit, unit_model, pos, None)
                       ,Wait(0.2)
                       ,Func(self.interface.setMarker, unit_model.id)
                       ,Func(self.interface.console.consoleOutput, 'Unit spotted!', utils.CONSOLE_SYSTEM_MESSAGE)
                       ,Func(self.interface.console.show)
                       )
    
    def buildDeleteAnim(self, unit_id):
        return Sequence(Func(self.interface.clearMarker, unit_id), Func(self.sgm.hideUnit, unit_id), Func(self.deleteUnit, unit_id), Wait(0.2))
    
    def buildDetachAnim(self, unit_id):
        return Sequence(Func(self.sgm.detachUnit, unit_id), Wait(0.2))
    
    def buildOverwatchAnim(self, action_list):
        i = self.buildShoot(action_list)
        return i
    
    def handleShoot(self, action_list):
        shoot = self.buildShoot(action_list)
        s = Sequence(Func(self.beforeAnimHook), Wait(0.2), shoot, Func(self.afterAnimHook))
        s.start()        
    
    def buildShoot(self, action_list):
        s = Sequence()
        d = 0.0
        for action in action_list:
            action_type = action[0]
            
            if action_type == "shoot":
                shooter_id = action[1] # unit_id of the shooter
                shoot_tile = action[2] # (x,y) pos of targeted tile
                weapon = action[3] # weapon id
                damage_list = action[4] # list of all damaged/missed/bounced/killed units
                if shooter_id >= 0:
                    shooter_model = self.sgm.unit_np_dict[shooter_id]
                    a = self.buildShootAnim(shooter_model, weapon)
                    shooter_pos =  Point3(utils.TILE_SIZE*(self.units[shooter_id]['pos'][0] + 0.5), 
                                          utils.TILE_SIZE*(self.units[shooter_id]['pos'][1] + 0.5),
                                          utils.GROUND_LEVEL
                                          )
                    b = self.buildBulletAnim(shooter_pos, shoot_tile)
                    i = self.buildDamageAnim(damage_list)
                    bi = Sequence(b, i)
                    s.append(Parallel(a, bi))                    
            #if action_type == "shoot":
            #    shooter_id = action[1] # unit_id of the shooter
            #    shoot_tile = action[2] # (x,y) pos of targeted tile
            #    weapon = action[3] # weapon id
            #    damage_list = action[4] # list of all damaged/missed/bounced/killed units
            #    if shooter_id >= 0:
            #        shooter_model = self.sgm.unit_np_dict[shooter_id]
            #        a = self.buildShootAnim(shooter_model, weapon)
            #        b = Sequence(Func(self.buildLaserAnim, shooter_model.node, self.sgm.unit_np_dict[damage_list[0][1]].node))
            #        i = self.buildDamageAnim(damage_list)
            #        bi = Sequence(b, i)
            #        s.append(Parallel(a, bi))

            elif action_type == "melee":
                shooter_id = action[1] # unit_id of the shooter
                shoot_tile = action[2] # (x,y) pos of targeted tile
                weapon = action[3] # weapon id
                damage_list = action[4] # list of all damaged/missed/bounced/killed units
                shooter_model = self.sgm.unit_np_dict[shooter_id]
                i = self.buildMeleeAnim(shooter_model, shoot_tile, weapon)
                s.append(i)
                i = self.buildDamageAnim(damage_list)
                s.append(i)
            elif action_type == "rotate":
                unit_id = action[1]
                heading = action[2]
                unit_model = self.sgm.unit_np_dict[unit_id]
                start_h = utils.getHeadingAngle(self.units[unit_id]['heading'])
                i, duration, pos, h = self.buildRotateAnim(unit_model, None, None, start_h, heading)
                s.append(i)
            elif action_type == "overwatch":
                action_list = action[1]
                i = self.buildOverwatchAnim(action_list)
                s.append(i)
        
        # Start our shoot sequence
        return s
    
    def buildShootAnim(self, unit_model, weapon):
        # Unit shooting animation
        shoot_anim = Func(unit_model.fsm.request, 'Shoot')
        return shoot_anim
    
    def buildBulletAnim(self, start_pos, target_tile):
        # We create the bullet and its animation
        self.bullet = loader.loadModel("sphere")
        self.bullet.setScale(0.05)
        start_pos = Point3(start_pos.getX(), start_pos.getY(), 0.9)
        end_pos = Point3(utils.TILE_SIZE*(target_tile[0] + 0.5), utils.TILE_SIZE*(target_tile[1] + 0.5), 0.9)
        dest_node = NodePath("dest_node")
        dest_node.setPos(end_pos)
        start_node = NodePath("start_node")
        start_node.setPos(start_pos)
        time = round(start_node.getDistance(dest_node) / utils.BULLET_SPEED, 2)
        bullet_sequence = Sequence(Func(self.sgm.setBullet, self.bullet),
                                   self.bullet.posInterval(time, end_pos, start_pos),
                                   Func(self.sgm.deleteBullet, self.bullet)
                                   )
        return bullet_sequence
    
    def buildLaserAnim(self, source, target):
        self.combat.source = source
        self.combat.target = target
        taskMgr.add(self.combat.drawBeam, 'beamtask')
        

    def buildMeleeAnim(self, unit_model, target_tile, weapon):
        # Unit melee animation
        melee_anim = Func(unit_model.fsm.request, 'Melee')
        return melee_anim
    
    def buildDamageAnim(self, damage_list):
        # Find all damaged units and play their damage/kill/miss animation
        damage_parallel = Parallel()
        for action in damage_list:
            damage_type = action[0]
            target_unit_id = action[1]
            target_unit = self.sgm.unit_np_dict[target_unit_id]
            t = TextNode('dmg')
            if damage_type == "bounce":
                target_anim = Func(target_unit.fsm.request, 'GetHit') 
                dmg = 'bounce'
            elif damage_type == "miss":
                target_anim = Func(target_unit.fsm.request, 'GetHit') 
                dmg = 'miss'                
            elif damage_type == "damage":
                color_interval = Sequence(LerpColorScaleInterval(target_unit.model, 0.2, (10,10,10,1))
                                         ,LerpColorScaleInterval(target_unit.model, 0.2, (1,1,1,1)))
                target_anim = Sequence(Func(target_unit.fsm.request, 'GetHit') , color_interval)
                dmg = str(action[2])
            elif damage_type == "kill":
                color_interval = Sequence(LerpColorScaleInterval(target_unit.model, 0.2, (10,10,10,1))
                                         ,LerpColorScaleInterval(target_unit.model, 0.2, (1,1,1,1)))                
                target_anim = Parallel(Func(target_unit.fsm.request, 'Die') , color_interval)
                dmg = str(action[2])
            t.setText( "%s" % dmg)
            t.setTextColor(1, 0, 0, 1)
            t.setAlign(TextNode.ACenter)
            textNodePath = NodePath("textnp")
            textNodePath.attachNewNode(t)
            textNodePath.setScale(0.35)
            textNodePath.setBillboardPointEye()
            textNodePath.setLightOff()
            # textNodePath will be reparented to unitmodel, so set start and end pos relative to the unit
            start_pos = Point3(0, 0, 0.9)
            end_pos = start_pos + Point3(0, 0, 3)
            damage_text_sequence = Sequence(Func(self.sgm.setDamageNode, textNodePath, target_unit.node),
                                            textNodePath.posInterval(1, end_pos, start_pos),
                                            Func(self.sgm.deleteDamageNode, textNodePath)
                                            ) 
            damage_parallel = Parallel(damage_text_sequence, target_anim)       
        return damage_parallel
    
    def handleVanish(self, unit_id):
        i = self.buildDeleteAnim(unit_id)
        s = Sequence(i, Func(self.afterAnimHook))
        s.start()
        
    def handleSpot(self, unit):
        self.units[unit['id']] = unit
        # This is the first time we see this unit, fill out starting variables for move and rotate actions
        wpn_list = utils.getUnitWeapons(unit)
        spotted_unit_model = self.sgm.loadUnit(unit['id'], wpn_list)

        pos = Point3(utils.TILE_SIZE*(self.units[unit['id']]['pos'][0] + 0.5), 
                     utils.TILE_SIZE*(self.units[unit['id']]['pos'][1] + 0.5),
                     utils.GROUND_LEVEL
                     )
        heading = utils.getHeadingAngle(self.units[unit['id']]['heading'])
        i = self.buildSpotAnim(spotted_unit_model, pos, heading)
        s = Sequence(i, Func(self.afterAnimHook))
        s.start()        
        
    def handleNewTurn(self):
        text = TextNode('new turn node')
        text.setText("TURN: "+self.turn_player)
        textnp = NodePath("textnp")
        textNodePath = textnp.attachNewNode(text)
        textNodePath.setColor(1, 0, 0)
        textNodePath.setScale(0.01, 0.01, 0.01)
        textNodePath.setPos(-0.7, 0, 0)
        textNodePath.reparentTo(aspect2d)
        s = Sequence(textNodePath.scaleInterval(.3, textNodePath.getScale()*20,blendType='easeIn'),
                     Wait(1.0),
                     textNodePath.scaleInterval(.3, textNodePath.getScale()*0.05,blendType='easeIn'),
                     Func(self.sgm.deleteTurnNode, textNodePath),
                     Func(self.afterAnimHook)
                     )
        s.start()
    
    def setCamPoss(self, off):
        self.altCam.setPos(self.altCam.getPos() + Point3(0, 0, 0.1)*off)
        print self.altCam.getPos()
   
    def setCamLook(self, off):
        self.altCam.setP(self.altCam.getP() + 0.5*off)
        print self.altCam.getP()     
        
    
    def deploySquadScreen(self):
        self.dr2 = base.win.makeDisplayRegion(0.0, 0.5, 0.65, 1.0)
        self.dr2.setClearColor(VBase4(0, 0, 0, 0.3))
        self.dr2.setClearColorActive(False)
        self.dr2.setClearDepthActive(True)

        self.render2 = NodePath('render2')
        self.cam2 = self.render2.attachNewNode(Camera('cam2'))
        self.cam2.node().getLens().setAspectRatio(1.8)
        self.dr2.setCamera(self.cam2)
        
        self.floor2np = self.render2.attachNewNode('floor2')
        tex = loader.loadTexture('scifi_floor.png')  
        tex.setMagfilter(Texture.FTLinearMipmapLinear)
        tex.setMinfilter(Texture.FTLinearMipmapLinear)
        cm = CardMaker('cm_floor')
        cm.setFrame(0, 1, 0, 1)        
        for x in xrange(10):
            for y in xrange(10):        
                cpos = self.floor2np.attachNewNode(cm.generate())
                cpos.setPos(x-5, y-5, 0)
                cpos.setP(-90)
                cpos.setTexture(tex)
        self.floor2np.flattenStrong()
        self.cam2.setPos(0, -10, 5)
        self.cam2.setP(-20)
        
        for idx, u in enumerate(self.deploy_queue):
            unit = utils.loadUnit('marine', u.lower(), self.player_id)
            unit.reparentTo(self.render2)
            unit.setScale(1)
            if idx == 0:
                unit.setPos(0, 0, 0)
            elif idx == 1:
                unit.setPos(1.5, 1.5, 0)
                unit.setH(-20)
            elif idx == 2:
                unit.setPos(-1.5, 1.8, 0)
                unit.setH(-10)
            elif idx == 3:
                unit.setPos(2.2, 2.5, 0)
                unit.setH(-20)
            elif idx == 4:
                unit.setPos(-1.4, 3.5, 0)
            elif idx == 5:
                unit.setPos(3.5, -0.5, 0)
                unit.setH(-35)
            elif idx == 6:
                unit.setPos(-2.6, 2.5, 0)
                unit.setH(30)
            elif idx == 7:
                unit.setPos(-4.5, 0, 0)
                unit.setH(40)
            unit.setTag('id', str(idx))
            unit.setTag('type', u.lower())
        
        self.altalight = AmbientLight("alight")
        self.altalight.setColor(VBase4(0.2, 0.2, 0.2, 1.0))
        self.altalnp = self.render2.attachNewNode(self.altalight)
        self.render2.setLight(self.altalnp)
        
        self.altalight2 = AmbientLight("alight2")
        self.altalight2.setColor(VBase4(0.4, 0.4, 0.4, 1.0))
        self.altalnp2 = self.render2.attachNewNode(self.altalight2)
        

        self.altslight = Spotlight('slight')
        self.altslight.setColor(VBase4(0.6, 0.6, 0.6, 1))
        self.altslnp = self.render2.attachNewNode(self.altslight)
        self.altslnp.setPos(5, 1, 15)
        self.altslnp.lookAt(0, 0, 0)
        self.render2.setLight(self.altslnp) 
        
        self.render2.setShaderAuto()
        
        self.deploy_index = 0
        self.deploy_unit_np = render.attachNewNode('deploy_unit_np')
        self.getDeployee()
        
    def getDeployee(self):
        if len(self.deploy_queue) > self.deploy_index:
            self.deploy_unit = self.render2.find('=id='+str(self.deploy_index))
            self.deploy_unit.setLight(self.altalnp2)
            self.deploy_index += 1
        else:
            self.deploy_unit = None
    
    def deployUnit(self):
        if self.deploy_unit != None:
            if base.mouseWatcherNode.hasMouse():
                mpos = base.mouseWatcherNode.getMouse()
                pos3d = Point3()
                nearPoint = Point3()
                farPoint = Point3()
                base.camLens.extrude(mpos, nearPoint, farPoint)
                if self.plane.intersectsLine(pos3d, render.getRelativePoint(camera, nearPoint), render.getRelativePoint(camera, farPoint)):
                    pos = (int(pos3d.getX()), int(pos3d.getY()))
                    if self.deploy_dict.has_key(pos) and self.deploy_dict[pos] == None:
                        unit = self.deploy_unit
                        unit.reparentTo(self.deploy_unit_np)                        
                        unit.setScale(0.3)
                        unit.setPos(int(pos3d.getX()) + 0.5, int(pos3d.getY()) + 0.5, utils.GROUND_LEVEL)
                        self.deploy_dict[pos] = unit.getTag('type') 
                        self.deploy_unit.setLightOff()
                        self.getDeployee()
    
    def endDeploy(self):
        if len(self.deploy_queue) > self.deploy_index:
            print "You must deploy all units"
        else:
            army_list = []
            for key in self.deploy_dict:
                if self.deploy_dict[key] != None:
                    tup = (key[0], key[1], 'marine_'+self.deploy_dict[key])
                    army_list.append(tup)
            ClientMsg.armyList(army_list)
      
    @pstat
    def getInvisibleTiles(self):
        a = []
        for u in self.units:
            if self.isThisMyUnit(u):
                a.append(self.units[u])
        t = time.clock()
        l = levelVisibilityDict(a, self.level)
        print "tiles timer:::", (time.clock()-t)*1000
        return l
    
    @pstat
    def getInvisibleWalls(self):
        a = []
        for u in self.units:
            if self.isThisMyUnit(u):
                a.append(self.units[u])
        t = time.clock()
        l = visibleWalls(a, self.level)
        print "walls timer:::", (time.clock()-t)*1000
        return l
class TownLoader(StateData):
    notify = directNotify.newCategory("TownLoader")

    def __init__(self, hood, parentFSMState, doneEvent):
        self.hood = hood
        self.parentFSMState = parentFSMState
        StateData.__init__(self, doneEvent)
        self.fsm = ClassicFSM('TownLoader', [
            State('start', self.enterStart, self.exitStart,
                  ['quietZone', 'street', 'toonInterior']),
            State('street', self.enterStreet, self.exitStreet, ['quietZone']),
            State('toonInterior', self.enterToonInterior,
                  self.exitToonInterior, ['quietZone']),
            State('suitInterior', self.enterSuitInterior,
                  self.exitSuitInterior, ['quietZone']),
            State('quietZone', self.enterQuietZone, self.exitQuietZone,
                  ['street', 'toonInterior', 'suitInterior']),
            State('final', self.enterFinal, self.exitFinal, ['start'])
        ], 'start', 'final')
        self.branchZone = None
        self.canonicalBranchZone = None
        self.placeDoneEvent = 'placeDone'
        self.streetSong = ''
        self.interiorSong = ''
        self.linkTunnels = []
        self.place = None
        return

    def findAndMakeLinkTunnels(self, requestStatus):
        for tunnel in self.geom.findAllMatches('**/*linktunnel*'):
            dnaRootStr = tunnel.getName()
            zone = LinkTunnel.getZoneFromDNARootStr(dnaRootStr)
            zone = LinkTunnel.maybeFixZone(zone)
            tunnelClass = LinkTunnel.getRecommendedTunnelClassFromZone(zone)
            link = tunnelClass(tunnel, dnaRootStr)
            self.linkTunnels.append(link)

    def load(self, zoneId):
        StateData.load(self)
        self.zoneId = zoneId
        self.branchZone = ZoneUtil.getBranchZone(zoneId)
        self.canonicalBranchZone = ZoneUtil.getCanonicalBranchZone(zoneId)

    def unload(self):
        self.parentFSMState.removeChild(self.fsm)
        del self.parentFSMState
        del self.fsm
        del self.streetClass
        base.disablePhysicsNodes(self.landmarkBlocks)
        self.landmarkBlocks.removeNode()
        del self.landmarkBlocks
        self.hood.dnaStore.resetSuitPoints()
        self.hood.dnaStore.resetBattleCells()
        del self.hood
        del self.nodeDict
        del self.zoneDict
        del self.fadeInDict
        del self.fadeOutDict
        del self.nodeList
        del self.zoneVisDict

        base.disablePhysicsNodes(self.geom)
        self.geom.removeNode()
        del self.geom
        del self.streetSong
        del self.interiorSong

        #CIGlobals.doSceneCleanup()

        StateData.unload(self)

    def enter(self, requestStatus):
        StateData.enter(self)
        self.findAndMakeLinkTunnels(requestStatus)
        self.fsm.enterInitialState()
        self.setState(requestStatus['where'], requestStatus)

    def exit(self):
        self.fsm.requestFinalState()
        self.ignoreAll()
        ModelPool.garbageCollect()
        TexturePool.garbageCollect()
        StateData.exit(self)

    def setState(self, state, requestStatus):
        self.fsm.request(state, [requestStatus])

    def enterStart(self):
        pass

    def exitStart(self):
        pass

    def enterStreet(self, requestStatus):
        self.acceptOnce(self.placeDoneEvent, self.streetDone)
        self.place = self.streetClass(self, self.fsm, self.placeDoneEvent)
        self.place.load()

    def exitStreet(self):
        self.ignore(self.placeDoneEvent)
        self.place.exit()
        self.place.unload()
        self.place = None
        base.cr.playGame.setPlace(self.place)
        return

    def streetDone(self):
        self.requestStatus = self.place.doneStatus
        status = self.place.doneStatus
        if (status['loader'] == 'townLoader'
                and ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone
                and status['shardId'] is None or status['how'] == 'doorOut'
                or status['where'] == 'suitInterior'):
            self.fsm.request('quietZone', [status])
        else:
            self.doneStatus = status
            messenger.send(self.doneEvent)

    def enterToonInterior(self, requestStatus):
        self.acceptOnce(self.placeDoneEvent, self.handleToonInteriorDone)
        self.place = ToonInterior.ToonInterior(self, self.fsm,
                                               self.placeDoneEvent)
        self.place.load()

    def exitToonInterior(self):
        self.ignore(self.placeDoneEvent)
        self.place.exit()
        self.place.unload()
        self.place = None
        base.cr.playGame.setPlace(self.place)
        return

    def enterSuitInterior(self, requestStatus):
        self.acceptOnce(self.placeDoneEvent, self.handleSuitInteriorDone)
        self.place = CogOfficeInterior.CogOfficeInterior(
            self, self.fsm, self.placeDoneEvent)
        self.place.load()

    def exitSuitInterior(self):
        self.ignore(self.placeDoneEvent)
        self.place.exit()
        self.place.unload()
        self.place = None
        base.cr.playGame.setPlace(self.place)

    def enterThePlace(self, requestStatus):
        base.cr.playGame.setPlace(self.place)
        if self.place is not None:
            self.place.enter(requestStatus)

    def handleToonInteriorDone(self):
        status = self.place.doneStatus
        if (status['loader'] == 'townLoader'
                and ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone
                and status['shardId'] is None or status['how'] == 'doorOut'):
            self.fsm.request('quietZone', [status])
        else:
            self.doneStatus = status
            messenger.send(self.doneEvent)
        return

    def handleSuitInteriorDone(self):
        self.handleToonInteriorDone()

    def enterQuietZone(self, requestStatus):
        self.fsm.request(requestStatus['where'], [requestStatus],
                         exitCurrent=0)

        self.quietZoneDoneEvent = uniqueName('quietZoneDone')
        self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone)
        self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent)
        self.quietZoneStateData.load()
        self.quietZoneStateData.enter(requestStatus)

    def exitQuietZone(self):
        self.ignore(self.quietZoneDoneEvent)
        del self.quietZoneDoneEvent
        self.quietZoneStateData.exit()
        self.quietZoneStateData.unload()
        self.quietZoneStateData = None
        return

    def handleQuietZoneDone(self):
        status = self.quietZoneStateData.getRequestStatus()
        self.exitQuietZone()
        self.enterThePlace(status)

    def enterFinal(self):
        pass

    def exitFinal(self):
        pass

    def createHood(self, dnaFile, loadStorage=1, flattenNow=True):
        if loadStorage:
            loader.loadDNAFile(self.hood.dnaStore,
                               'phase_5/dna/storage_town.pdna')
            loader.loadDNAFile(self.hood.dnaStore, self.townStorageDNAFile)
        node = loader.loadDNAFile(self.hood.dnaStore, dnaFile)
        if node.getNumParents() == 1:
            self.geom = NodePath(node.getParent(0))
            self.geom.reparentTo(hidden)
        else:
            self.geom = hidden.attachNewNode(node)
        if flattenNow:
            self.doFlatten()
        self.geom.setName('town_top_level')

    def doFlatten(self):
        self.makeDictionaries(self.hood.dnaStore)
        self.reparentLandmarkBlockNodes()
        base.createPhysicsNodes(self.geom)
        self.renameFloorPolys(self.nodeList)
        self.geom.flattenLight()

        CIGlobals.preRenderScene(self.geom)

    def reparentLandmarkBlockNodes(self):
        bucket = self.landmarkBlocks = hidden.attachNewNode('landmarkBlocks')
        npc = self.geom.findAllMatches('**/sb*:*_landmark_*_DNARoot')
        for i in xrange(npc.getNumPaths()):
            nodePath = npc.getPath(i)
            nodePath.wrtReparentTo(bucket)

        npc = self.geom.findAllMatches('**/sb*:*animated_building*_DNARoot')
        for i in xrange(npc.getNumPaths()):
            nodePath = npc.getPath(i)
            nodePath.wrtReparentTo(bucket)

    def makeDictionaries(self, dnaStore):
        self.nodeDict = {}
        self.zoneDict = {}
        self.zoneVisDict = {}
        self.nodeList = []
        self.fadeInDict = {}
        self.fadeOutDict = {}
        a1 = Vec4(1, 1, 1, 1)
        a0 = Vec4(1, 1, 1, 0)
        numVisGroups = dnaStore.getNumDNAVisGroupsAI()
        for i in xrange(numVisGroups):
            groupFullName = dnaStore.getDNAVisGroupName(i)
            visGroup = dnaStore.getDNAVisGroupAI(i)
            groupName = base.cr.hoodMgr.extractGroupName(groupFullName)
            zoneId = int(groupName)
            zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId)
            groupNode = self.geom.find('**/' + groupFullName)
            if groupNode.isEmpty():
                continue
            else:
                if ':' in groupName:
                    groupName = '%s%s' % (zoneId,
                                          groupName[groupName.index(':'):])
                else:
                    groupName = '%s' % zoneId
                groupNode.setName(groupName)

            CIGlobals.replaceDecalEffectsWithDepthOffsetAttrib(groupNode)

            #group all the flat walls

            block2flatwall = {}
            flatwalls = groupNode.findAllMatches("**/tb*:*_DNARoot;+s")
            for flatwall in flatwalls:
                if "toon_landmark" in flatwall.getName():
                    print "Skipping", flatwall.getName()
                    continue
                if flatwall.hasTag("DNACode") and flatwall.hasMat():
                    continue
                block = int(flatwall.getName().split(":")[0][2:])
                if not block2flatwall.has_key(block):
                    block2flatwall[block] = groupNode.attachNewNode(
                        ModelNode('toonBuildingsBlock' + str(block)))
                flatwall.wrtReparentTo(block2flatwall[block])

            for node in block2flatwall.values():
                for child in node.findAllMatches("**"):
                    child.clearEffect(DecalEffect.getClassType())
                    child.clearTag("DNACode")
                    child.clearTag("cam")
                CIGlobals.clearModelNodesBelow(node)
                node.flattenStrong()

            flattenGroup = groupNode.attachNewNode('optim')
            flattens = ['street*_DNARoot']
            removes = ['interactive_prop*_DNARoot']
            for remove in removes:
                for np in groupNode.findAllMatches("**/" + remove):
                    np.removeNode()
            for flatten in flattens:
                for np in groupNode.findAllMatches("**/" + flatten):
                    if np.hasTag("DNACode") and np.hasMat():
                        continue
                    for child in np.findAllMatches("**"):
                        child.clearEffect(DecalEffect.getClassType())
                        child.clearTag("DNACode")
                        child.clearTag("cam")
                    np.wrtReparentTo(flattenGroup)
            flattenGroup.clearModelNodes()
            flattenGroup.flattenStrong()

            CIGlobals.flattenModelNodes(groupNode)
            groupNode.flattenStrong()
            #groupNode.ls()

            self.nodeDict[zoneId] = []
            self.nodeList.append(groupNode)
            self.zoneDict[zoneId] = groupNode
            visibles = []
            for i in xrange(visGroup.getNumVisibles()):
                visibles.append(int(visGroup.get_visible(i)))
            visibles.append(ZoneUtil.getBranchZone(zoneId))
            self.zoneVisDict[zoneId] = visibles
            fadeDuration = 0.5
            self.fadeOutDict[groupNode] = Sequence(
                Func(groupNode.setTransparency, 1),
                LerpColorScaleInterval(groupNode,
                                       fadeDuration,
                                       a0,
                                       startColorScale=a1),
                Func(groupNode.clearColorScale),
                Func(groupNode.clearTransparency),
                Func(groupNode.stash),
                Func(base.disablePhysicsNodes, groupNode),
                name='fadeZone-' + str(zoneId),
                autoPause=1)
            self.fadeInDict[groupNode] = Sequence(
                Func(base.enablePhysicsNodes, groupNode),
                Func(groupNode.unstash),
                Func(groupNode.setTransparency, 1),
                LerpColorScaleInterval(groupNode,
                                       fadeDuration,
                                       a1,
                                       startColorScale=a0),
                Func(groupNode.clearColorScale),
                Func(groupNode.clearTransparency),
                name='fadeZone-' + str(zoneId),
                autoPause=1)

        for i in xrange(numVisGroups):
            groupFullName = dnaStore.getDNAVisGroupName(i)
            zoneId = int(base.cr.hoodMgr.extractGroupName(groupFullName))
            zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId)
            for j in xrange(dnaStore.getNumVisiblesInDNAVisGroup(i)):
                visName = dnaStore.getVisibleName(i, j)
                groupName = base.cr.hoodMgr.extractGroupName(visName)
                nextZoneId = int(groupName)
                nextZoneId = ZoneUtil.getTrueZoneId(nextZoneId, self.zoneId)
                visNode = self.zoneDict[nextZoneId]
                self.nodeDict[zoneId].append(visNode)

        self.hood.dnaStore.resetPlaceNodes()
        self.hood.dnaStore.resetDNAGroups()
        self.hood.dnaStore.resetDNAVisGroups()
        self.hood.dnaStore.resetDNAVisGroupsAI()

    def renameFloorPolys(self, nodeList):
        for i in nodeList:
            collNodePaths = i.findAllMatches('**/+BulletRigidBodyNode')
            numCollNodePaths = collNodePaths.getNumPaths()
            visGroupName = i.node().getName()
            for j in xrange(numCollNodePaths):
                collNodePath = collNodePaths.getPath(j)
                bitMask = collNodePath.node().getIntoCollideMask()
                if bitMask == CIGlobals.FloorGroup:
                    collNodePath.node().setName(visGroupName)
                    collNodePath.setCollideMask(CIGlobals.StreetVisGroup)
Пример #10
0
class GunGameLevelLoader:
    notify = directNotify.newCategory('GunGameLevelLoader')
    LevelData = {'momada': {'name': CIGlobals.ToonBattleOriginalLevel, 
                  'camera': (
                           Point3(0.0, -25.8, 7.59), Vec3(0.0, 0.0, 0.0)), 
                  'models': [
                           'phase_11/models/lawbotHQ/LB_Zone03a.bam',
                           'phase_11/models/lawbotHQ/LB_Zone04a.bam',
                           'phase_11/models/lawbotHQ/LB_Zone7av2.bam',
                           'phase_11/models/lawbotHQ/LB_Zone08a.bam',
                           'phase_11/models/lawbotHQ/LB_Zone13a.bam',
                           'phase_10/models/cashbotHQ/ZONE17a.bam',
                           'phase_10/models/cashbotHQ/ZONE18a.bam',
                           'phase_11/models/lawbotHQ/LB_Zone22a.bam'], 
                  'parents': [
                            render,
                            'EXIT',
                            'EXIT',
                            'EXIT',
                            'ENTRANCE',
                            'ENTRANCE',
                            'ENTRANCE',
                            'EXIT'], 
                  'model_positions': [
                                    Point3(0.0, 0.0, 0.0),
                                    Point3(-1.02, 59.73, 0.0),
                                    Point3(0.0, 74.77, 0.0),
                                    Point3(0.0, 89.37, -13.5),
                                    Point3(16.33, -136.53, 0.0),
                                    Point3(-1.01, -104.4, 0.0),
                                    Point3(0.65, -23.86, 0.0),
                                    Point3(-55.66, -29.01, 0.0)], 
                  'model_orientations': [
                                       Vec3(0.0, 0.0, 0.0),
                                       Vec3(0.0, 0.0, 0.0),
                                       Vec3(90.0, 0.0, 0.0),
                                       Vec3(180.0, 0.0, 0.0),
                                       Vec3(97.0, 0.0, 0.0),
                                       Vec3(359.95, 0.0, 0.0),
                                       Vec3(90.0, 0.0, 0.0),
                                       Vec3(270.0, 0.0, 0.0)], 
                  'spawn_points': [
                                 (
                                  Point3(0, 0, 0), Vec3(0, 0, 0)),
                                 (
                                  Point3(-20, 50, 0), Vec3(0, 0, 0)),
                                 (
                                  Point3(20, 50, 0), Vec3(0, 0, 0)),
                                 (
                                  Point3(0, 120, 0), Vec3(0, 0, 0)),
                                 (
                                  Point3(0, 100, 0), Vec3(180, 0, 0)),
                                 (
                                  Point3(-90, 0, 0), Vec3(0, 0, 0)),
                                 (
                                  Point3(-170, 0, 0), Vec3(0, 0, 0)),
                                 (
                                  Point3(-90, 50, 0), Vec3(0, 0, 0)),
                                 (
                                  Point3(-170, 50, 0), Vec3(0, 0, 0)),
                                 (
                                  Point3(35, 250, 0), Vec3(-90, 0, 0)),
                                 (
                                  Point3(0, 285, 0), Vec3(180, 0, 0)),
                                 (
                                  Point3(-185, 250, 0), Vec3(90, 0, 0))]}, 
       'dg': {'name': CIGlobals.DaisyGardens, 
              'camera': (
                       Point3(-33.13, -3.2, 48.62), Vec3(326.31, 332.68, 0.0)), 
              'dna': [
                    'phase_8/dna/storage_DG.pdna',
                    'phase_8/dna/storage_DG_sz.pdna',
                    'phase_8/dna/daisys_garden_sz.pdna'], 
              'sky': 'TT', 
              'spawn_points': hoodMgr.dropPoints[CIGlobals.DaisyGardens]}, 
       'mml': {'name': CIGlobals.MinniesMelodyland, 
               'camera': (
                        Point3(-54.42, -91.05, 34.89), Vec3(315.29, 336.8, 0.0)), 
               'dna': [
                     'phase_6/dna/storage_MM.pdna',
                     'phase_6/dna/storage_MM_sz.pdna',
                     'phase_6/dna/minnies_melody_land_sz.pdna'], 
               'sky': 'MM', 
               'spawn_points': hoodMgr.dropPoints[CIGlobals.MinniesMelodyland]}, 
       'oz': {'name': CIGlobals.OutdoorZone, 
              'camera': (
                       Point3(-54.42, -91.05, 34.89), Vec3(315.29, 336.8, 0.0)), 
              'dna': [
                    'phase_6/dna/storage_OZ.pdna',
                    'phase_6/dna/storage_OZ_sz.pdna',
                    'phase_6/dna/outdoor_zone_sz.pdna'], 
              'sky': 'TT', 
              'spawn_points': hoodMgr.dropPoints[CIGlobals.OutdoorZone]}, 
       'cbhq': {'name': CIGlobals.CashbotHQ, 
                'camera': (
                         Point3(302.64, 5.0, 15.2), Vec3(135.0, 341.57, 0.0)), 
                'model': 'phase_10/models/cogHQ/CashBotShippingStation.bam', 
                'sky': None, 
                'spawn_points': hoodMgr.dropPoints[CIGlobals.CashbotHQ]}, 
       'sbf': {'name': CIGlobals.SellbotFactory, 
               'camera': (
                        Point3(0, 0, 0), Vec3(0, 0, 0)), 
               'model': 'phase_9/models/cogHQ/SelbotLegFactory.bam', 
               'sky': 'cog', 
               'sky_scale': 10.0, 
               'occluders': 'phase_9/models/cogHQ/factory_sneak_occluders.egg', 
               'spawn_points': {GGG.Teams.BLUE: [
                                               (
                                                Point3(13, 30, 3.73), Point3(0, 0, 0)), (Point3(21, 30, 3.73), Point3(0, 0, 0)), (Point3(29, 30, 3.73), Point3(0, 0, 0)),
                                               (
                                                Point3(13, 20, 3.73), Point3(0, 0, 0)), (Point3(21, 20, 3.73), Point3(0, 0, 0)), (Point3(29, 30, 3.73), Point3(0, 0, 0))], 
                                GGG.Teams.RED: [
                                              (
                                               Point3(-644.43, 378.12, 8.73), Point3(270, 0, 0)), (Point3(-644.43, 370.75, 8.73), Point3(270, 0, 0)), (Point3(-644.43, 363.22, 8.73), Point3(270, 0, 0)),
                                              (
                                               Point3(-659.05, 378.12, 8.73), Point3(270, 0, 0)), (Point3(-659.05, 370.75, 8.73), Point3(270, 0, 0)), (Point3(-659.05, 363.22, 8.73), Point3(270, 0, 0))]}, 
               'flag_points': {GGG.Teams.BLUE: [Point3(213.23, 340.59, 19.73), Point3(90, 0, 0)], GGG.Teams.RED: [
                                             Point3(-543.6, 595.79, 9.73), Point3(270, 0, 0)]}, 
               'flagpoint_points': {GGG.Teams.BLUE: [Point3(-543.6, 595.79, 9.73), Point3(270, 0, 0)], GGG.Teams.RED: [
                                                  Point3(213.23, 340.59, 19.73), Point3(0, 0, 0)]}}, 
       'ttc': {'name': CIGlobals.ToontownCentral, 
               'dna': [
                     'phase_4/dna/storage_TT.pdna',
                     'phase_4/dna/storage_TT_sz.pdna',
                     'phase_4/dna/new_ttc_sz.pdna'], 
               'sky': 'TT', 
               'spawn_points': [
                              (9.90324401855, 91.9139556885, 8.0364112854, -545.909545898, 0.0, 0.0),
                              (77.9181442261, 50.953086853, 7.52815723419, -598.509460449, 0.0, 0.0),
                              (93.7379760742, 6.37303066254, 7.99749088287, -626.209533691, 0.0, 0.0),
                              (39.0383415222, -81.5989837646, 8.01874637604, -694.309265137, 0.0, 0.0),
                              (-19.2093048096, -95.1359481812, 8.07303524017, -731.409240723, 0.0, 0.0),
                              (-84.4093933105, -45.4780502319, 8.06541728973, -781.809143066, 0.0, 0.0),
                              (-92.2512283325, 2.41426730156, 8.03108692169, -811.70916748, 0.0, 0.0),
                              (46.8868179321, 81.3593673706, 8.04793071747, -955.309509277, 0.0, 0.0),
                              (32.3203735352, 90.0017929077, 8.06353855133, -884.409301758, 0.0, 0.0)], 
               'cap_point': Point3(-1.5, 0, 0)}}
    SkyData = {'TT': 'phase_3.5/models/props', 
       'MM': 'phase_6/models/props', 
       'cog': 'phase_9/models/cogHQ', 
       'MovingSkies': [
                     'TT']}

    def __init__(self, mg):
        self.mg = mg
        self.levelName = None
        self.dnaStore = DNAStorage()
        self.loadingText = None
        self.levelGeom = None
        self.skyUtil = None
        self.skyModel = None
        self.occluders = None
        self.momadaAreas = []
        self.momadaAreaName2areaModel = {}
        return

    def getFlagPoint_Point(self, team):
        return self.LevelData[self.levelName]['flagpoint_points'][team]

    def getFlagPoint(self, team):
        return self.LevelData[self.levelName]['flag_points'][team]

    def getCapturePoint(self):
        return self.LevelData[self.levelName]['cap_point']

    def setLevel(self, level):
        self.levelName = level

    def getLevel(self):
        return self.levelName

    def getCameraOfCurrentLevel(self):
        return self.LevelData[self.getLevel()]['camera']

    def getSpawnPoints(self):
        pointData = self.LevelData[self.levelName]['spawn_points']
        if self.levelName == 'momada':
            return pointData
        if self.mg.gameMode in [GGG.GameModes.CASUAL, GGG.GameModes.KOTH]:
            array = []
            for posAndHpr in pointData:
                array.append((
                 Point3(posAndHpr[0], posAndHpr[1], posAndHpr[2]),
                 Vec3(posAndHpr[3], posAndHpr[4], posAndHpr[5])))

        else:
            if self.mg.gameMode == GGG.GameModes.CTF:
                array = pointData[self.mg.team]
        return array

    def getNameOfCurrentLevel(self):
        return self.LevelData[self.getLevel()]['name']

    def load(self):
        self.unload()
        if self.loadingText:
            self.loadingText.destroy()
            self.loadingText = None
        self.loadingText = OnscreenText(text='', font=CIGlobals.getMinnieFont(), fg=(1,
                                                                                     1,
                                                                                     1,
                                                                                     1))
        self.loadingText.setBin('gui-popup', 0)
        base.graphicsEngine.renderFrame()
        base.graphicsEngine.renderFrame()
        if self.levelName == 'momada':
            self.__momadaLoad()
        else:
            if self.levelName in ('cbhq', 'sbf'):
                modelPath = self.LevelData[self.levelName]['model']
                self.levelGeom = loader.loadModel(modelPath)
                self.levelGeom.flattenMedium()
                self.levelGeom.reparentTo(render)
                if self.LevelData[self.levelName]['sky'] != None:
                    self.skyModel = loader.loadModel(self.SkyData['cog'] + '/cog_sky.bam')
                    self.skyUtil = SkyUtil()
                    self.skyUtil.startSky(self.skyModel)
                    self.skyModel.reparentTo(render)
                    self.skyModel.setScale(self.LevelData[self.levelName].get('sky_scale', 1.0))
                if self.LevelData[self.levelName].get('occluders'):
                    self.occluders = loader.loadModel(self.LevelData[self.levelName]['occluders'])
                    for occluderNode in self.occluders.findAllMatches('**/+OccluderNode'):
                        base.render.setOccluder(occluderNode)
                        occluderNode.node().setDoubleSided(True)

                if self.levelName == 'sbf':
                    base.camLens.setFar(250)
            else:
                dnaFiles = self.LevelData[self.levelName]['dna']
                skyType = self.LevelData[self.levelName]['sky']
                skyPhase = self.SkyData[skyType]
                loadDNAFile(self.dnaStore, 'phase_4/dna/storage.pdna')
                for index in range(len(dnaFiles)):
                    if index == len(dnaFiles) - 1:
                        node = loadDNAFile(self.dnaStore, dnaFiles[index])
                        if node.getNumParents() == 1:
                            self.levelGeom = NodePath(node.getParent(0))
                            self.levelGeom.reparentTo(hidden)
                        else:
                            self.levelGeom = hidden.attachNewNode(node)
                        if self.levelName == 'ttc' and dnaFiles[index] == 'phase_4/dna/new_ttc_sz.pdna':
                            self.levelGeom.find('**/prop_gazebo_DNARoot').removeNode()
                        else:
                            self.levelGeom.flattenMedium()
                        gsg = base.win.getGsg()
                        if gsg:
                            self.levelGeom.prepareScene(gsg)
                        self.levelGeom.reparentTo(render)
                    else:
                        loadDNAFile(self.dnaStore, dnaFiles[index])

                children = self.levelGeom.findAllMatches('**/*doorFrameHole*')
                for child in children:
                    child.hide()

                self.skyModel = loader.loadModel(skyPhase + '/' + skyType + '_sky.bam')
                self.skyUtil = SkyUtil()
                self.skyUtil.startSky(self.skyModel)
                self.skyModel.reparentTo(camera)
                ce = CompassEffect.make(NodePath(), CompassEffect.PRot | CompassEffect.PZ)
                self.skyModel.node().setEffect(ce)
        if self.loadingText:
            self.loadingText.destroy()
            self.loadingText = None
        return

    def __momadaLoad(self):

        def attachArea(itemNum):
            name = 'MomadaArea-%s' % itemNum
            area = self.momadaAreaName2areaModel.get(name)
            parents = self.LevelData['momada']['parents']
            parent = parents[itemNum]
            if type(parent) == type(''):
                parent = self.momadaAreas[itemNum - 1].find('**/' + parent)
            pos = self.LevelData['momada']['model_positions'][itemNum]
            hpr = self.LevelData['momada']['model_orientations'][itemNum]
            area.reparentTo(parent)
            area.setPos(pos)
            area.setHpr(hpr)

        _numItems = 0
        name = None
        for item in self.LevelData['momada']['models']:
            name = 'MomadaArea-%s' % _numItems
            area = loader.loadModel(item)
            self.momadaAreas.append(area)
            self.momadaAreaName2areaModel[name] = area
            attachArea(_numItems)
            _numItems += 1
            self.notify.info('Loaded and attached %s momada areas.' % _numItems)

        return

    def unload(self):
        render.clearOccluder()
        if self.levelName == 'sbf':
            base.camLens.setFar(CIGlobals.DefaultCameraFar)
        if self.levelName == 'momada':
            for area in self.momadaAreas:
                self.momadaAreas.remove(area)
                area.removeNode()
                del area

            self.momadaAreas = []
            self.momadaAreaName2areaModel = {}
        else:
            if self.occluders:
                self.occluders.removeNode()
                self.occluders = None
            if self.skyUtil:
                self.skyUtil.stopSky()
                self.skyUtil = None
            if self.skyModel:
                self.skyModel.removeNode()
                self.skyModel = None
            if self.levelGeom:
                self.levelGeom.removeNode()
                self.levelGeom = None
        return

    def cleanup(self):
        self.momadaAreas = None
        self.momadaAreaName2areaModel = None
        if self.dnaStore:
            self.dnaStore.reset_nodes()
            self.dnaStore.reset_hood_nodes()
            self.dnaStore.reset_place_nodes()
            self.dnaStore.reset_hood()
            self.dnaStore.reset_fonts()
            self.dnaStore.reset_DNA_vis_groups()
            self.dnaStore.reset_textures()
            self.dnaStore.reset_block_numbers()
            self.dnaStore.reset_block_zones()
            self.dnaStore.reset_suit_points()
        self.dnaStore = None
        return
Пример #11
0
class SafeZoneLoader(StateData):
    notify = directNotify.newCategory('SafeZoneLoader')

    def __init__(self, hood, parentFSMState, doneEvent):
        StateData.__init__(self, doneEvent)
        self.hood = hood
        self.parentFSMState = parentFSMState
        self.fsm = ClassicFSM('safeZoneLoader', [
            State('off', self.enterOff, self.exitOff),
            State('playground', self.enterPlayground, self.exitPlayground,
                  ['quietZone']),
            State('toonInterior', self.enterToonInterior,
                  self.exitToonInterior, ['quietZone']),
            State('quietZone', self.enterQuietZone, self.exitQuietZone,
                  ['playground', 'toonInterior'])
        ], 'off', 'off')
        self.placeDoneEvent = 'placeDone'
        self.place = None
        self.playground = None
        self.battleMusic = None
        self.invasionMusic = None
        self.invasionMusicFiles = None
        self.interiorMusic = None
        self.bossBattleMusic = None
        self.music = None
        self.tournamentMusic = None
        self.linkTunnels = []
        self.szHolidayDNAFile = None
        self.animatedFish = None
        return

    def findAndMakeLinkTunnels(self):
        for tunnel in self.geom.findAllMatches('**/*linktunnel*'):
            dnaRootStr = tunnel.getName()
            link = LinkTunnel.SafeZoneLinkTunnel(tunnel, dnaRootStr)
            self.linkTunnels.append(link)

    def load(self):
        StateData.load(self)
        if self.pgMusicFilename:
            if type(self.pgMusicFilename) == types.ListType:
                filename = random.choice(self.pgMusicFilename)
            else:
                filename = self.pgMusicFilename
            self.music = base.loadMusic(filename)
        if self.battleMusicFile:
            self.battleMusic = base.loadMusic(self.battleMusicFile)
        if self.invasionMusicFiles:
            self.invasionMusic = None
        if self.bossBattleMusicFile:
            self.bossBattleMusic = base.loadMusic(self.bossBattleMusicFile)
        if self.interiorMusicFilename:
            self.interiorMusic = base.loadMusic(self.interiorMusicFilename)
        if self.tournamentMusicFiles:
            self.tournamentMusic = None
        self.createSafeZone(self.dnaFile)
        children = self.geom.findAllMatches('**/*doorFrameHole*')
        for child in children:
            child.hide()

        self.parentFSMState.addChild(self.fsm)
        _, _, _, _, _, _, _, _, af = SettingsManager().getSettings(
            'settings.json')
        if af == 'on':
            self.notify.info(
                'Anisotropic Filtering is on, applying to textures.')
            for nodepath in self.geom.findAllMatches('*'):
                try:
                    for node in nodepath.findAllMatches('**'):
                        try:
                            node.findTexture('*').setAnisotropicDegree(8)
                        except:
                            pass

                except:
                    continue

        return

    def unload(self):
        StateData.unload(self)
        if self.animatedFish:
            self.animatedFish.cleanup()
            self.animatedFish.removeNode()
            self.animatedFish = None
        self.parentFSMState.removeChild(self.fsm)
        del self.parentFSMState
        del self.animatedFish
        self.geom.removeNode()
        del self.geom
        del self.fsm
        del self.hood
        del self.playground
        del self.music
        del self.interiorMusic
        del self.battleMusic
        del self.bossBattleMusic
        del self.tournamentMusic
        self.ignoreAll()
        ModelPool.garbageCollect()
        TexturePool.garbageCollect()
        return

    def enter(self, requestStatus):
        StateData.enter(self)
        if base.localAvatar.zoneId < CIGlobals.DynamicZonesBegin:
            self.findAndMakeLinkTunnels()
        self.fsm.enterInitialState()
        messenger.send('enterSafeZone')
        self.setState(requestStatus['where'], requestStatus)
        partyGate = self.geom.find('**/prop_party_gate_DNARoot')
        if not partyGate.isEmpty():
            partyGate.removeNode()
        del partyGate
        petShop = self.geom.find('**/*pet_shop_DNARoot*')
        if not petShop.isEmpty():
            fish = petShop.find(
                '**/animated_prop_PetShopFishAnimatedProp_DNARoot')
            if fish:
                self.animatedFish = Actor(
                    'phase_4/models/props/exteriorfish-zero.bam',
                    {'chan': 'phase_4/models/props/exteriorfish-swim.bam'})
                self.animatedFish.reparentTo(petShop)
                self.animatedFish.setPos(fish.getPos())
                self.animatedFish.loop('chan')
                fish.removeNode()

    def exit(self):
        StateData.exit(self)
        messenger.send('exitSafeZone')
        for link in self.linkTunnels:
            link.cleanup()

        if self.animatedFish:
            self.animatedFish.stop('chan')
        self.linkTunnels = []

    def setState(self, stateName, requestStatus):
        self.fsm.request(stateName, [requestStatus])

    def createSafeZone(self, dnaFile):
        if self.szStorageDNAFile:
            loader.loadDNAFile(self.hood.dnaStore, self.szStorageDNAFile)
        if self.szHolidayDNAFile:
            loader.loadDNAFile(self.hood.dnaStore, self.szHolidayDNAFile)
        node = loader.loadDNAFile(self.hood.dnaStore, dnaFile)
        if node.getNumParents() == 1:
            self.geom = NodePath(node.getParent(0))
            self.geom.reparentTo(hidden)
        else:
            self.geom = hidden.attachNewNode(node)
        self.makeDictionaries(self.hood.dnaStore)
        if self.__class__.__name__ not in ('TTSafeZoneLoader', ):
            self.geom.flattenMedium()
        gsg = base.win.getGsg()
        if gsg:
            self.geom.prepareScene(gsg)

    def makeDictionaries(self, dnaStore):
        self.nodeList = []
        for i in xrange(dnaStore.getNumDNAVisGroups()):
            groupFullName = dnaStore.getDNAVisGroupName(i)
            groupNode = self.geom.find('**/' + groupFullName)
            if groupNode.isEmpty():
                self.notify.error('Could not find visgroup')
            if self.__class__.__name__ not in ('TTSafeZoneLoader', ):
                groupNode.flattenMedium()
            self.nodeList.append(groupNode)

        self.hood.dnaStore.resetPlaceNodes()
        self.hood.dnaStore.resetDNAGroups()
        self.hood.dnaStore.resetDNAVisGroups()
        self.hood.dnaStore.resetDNAVisGroupsAI()

    def enterPlayground(self, requestStatus):
        try:
            self.hood.stopSuitEffect()
        except:
            pass

        self.acceptOnce(self.placeDoneEvent, self.handlePlaygroundDone)
        self.place = self.playground(self, self.fsm, self.placeDoneEvent)
        self.place.load()

    def exitPlayground(self):
        self.ignore(self.placeDoneEvent)
        self.place.exit()
        self.place.unload()
        self.place = None
        base.cr.playGame.setPlace(self.place)
        return

    def handlePlaygroundDone(self):
        status = self.place.doneStatus
        if self.hood.isSameHood(status) and status[
                'loader'] == 'safeZoneLoader' and status['where'] not in (
                    'minigame', ):
            self.fsm.request('quietZone', [status])
        else:
            self.doneStatus = status
            messenger.send(self.doneEvent)

    def enterToonInterior(self, requestStatus):
        self.acceptOnce(self.placeDoneEvent, self.handleToonInteriorDone)
        self.place = ToonInterior.ToonInterior(self, self.fsm,
                                               self.placeDoneEvent)
        self.place.load()

    def enterThePlace(self, requestStatus):
        base.cr.playGame.setPlace(self.place)
        if self.place is not None:
            self.place.enter(requestStatus)
        return

    def exitToonInterior(self):
        self.ignore(self.placeDoneEvent)
        self.place.exit()
        self.place.unload()
        self.place = None
        base.cr.playGame.setPlace(self.place)
        return

    def handleToonInteriorDone(self):
        status = self.place.doneStatus
        if status['loader'] == 'safeZoneLoader' and self.hood.isSameHood(
                status
        ) and status['shardId'] == None or status['how'] == 'doorOut':
            self.fsm.request('quietZone', [status])
        else:
            self.doneStatus = status
            messenger.send(self.doneEvent)
        return

    def enterQuietZone(self, requestStatus):
        self.fsm.request(requestStatus['where'], [requestStatus],
                         exitCurrent=0)
        self.quietZoneDoneEvent = uniqueName('quietZoneDone')
        self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone)
        self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent)
        self.quietZoneStateData.load()
        self.quietZoneStateData.enter(requestStatus)

    def exitQuietZone(self):
        self.ignore(self.quietZoneDoneEvent)
        del self.quietZoneDoneEvent
        self.quietZoneStateData.exit()
        self.quietZoneStateData.unload()
        self.quietZoneStateData = None
        return

    def handleQuietZoneDone(self):
        status = self.quietZoneStateData.getDoneStatus()
        self.exitQuietZone()
        if status['where'] == 'estate' or status['loader'] == 'townLoader':
            self.doneStatus = status
            messenger.send(self.doneEvent)
        else:
            self.enterThePlace(status)

    def enterOff(self):
        pass

    def exitOff(self):
        pass
Пример #12
0
class Builder(object):

	def __init__(self,environment,nodes,lights,cameras,entities,animations,staticGeoms,yamlList):

		self.node = NodePath('fred')

		self.reset()

		self.environment = environment
		self.nodes       = nodes
		self.lights      = lights
		self.cameras     = cameras         
		self.entities    = entities       
		self.animations  = animations
		self.staticGeoms = staticGeoms
		self.yamlList    = yamlList

		self.initManagers()

	def initManagers(self):
		from pandark.managers.physicsmanager import PhysicsManager
		self.physicsMgr = PhysicsManager()

		from pandark.managers.lightsmanager import LightsManager
		self.lightsMgr = LightsManager()

		from pandark.managers.camerasmanager import CamerasManager
		self.camerasMgr = CamerasManager()

		from pandark.managers.animationsmanager import AnimationsManager
		self.animsMgr = AnimationsManager()

	def begin(self):
		base.setBackgroundColor( self.environment['colourBackground'] )

		alight = AmbientLight('AmbientLight')
		alight.setColor(self.environment['colourAmbient'] )
		alnp = self.node.attachNewNode(alight)
		self.node.setLight(alnp)

		if self.environment['fog']:
			fog = Fog( 'sceneName' )
			fog.setColor( self.environment['fog']['color'] )

			if self.environment['fog']['mode'] == "linear":
				fog.setLinearRange(self.environment['fog']['linearStart']*1000,self.environment['fog']['linearEnd']*1000)
			else:
				fog.setExpDensity( self.environment['fog']['expDensity'] )

			self.node.setFog(fog)

		[self.createNode(props) for props in self.nodes]
		[self.createLight(props) for props in self.lights]
		[self.createCamera(props) for props in self.cameras]
		[self.createEntity(props) for props in self.entities]
		[self.createStaticGeoms(props) for props in self.staticGeoms]


		#self.animsMgr.play('Camera01', 'idle', True) 

	def reset(self):		
		self.__nodesDict    = {}
		self.__lightsDict   = {}
		self.__camerasDict  = {}
		self.__entitiesDict = {}

		self.__nodesDict[''] = self.node

	def getEnt(self,name):		
		return self.__entitiesDict[name]

	def createNode(self,props):
		parent = self.node.find('**/'+props['groupName']) or self.node

		node = NodePath(props['name'])

		node.setPos(props['pos'])

		node.setQuat(props['quat'])

		node.setScale(props['scale'])

		node.reparentTo(parent)

		self.animsMgr.createAnimation(node, self.animations[ props['name'] ] )

		#self.__nodesDict[props['name']] = node

	def createLight(self,props):
		light = self.lightsMgr.createLight[props['type'] ](props)
		self.animsMgr.createAnimation(light, self.animations[ props['name'] ] )

	def createCamera(self,props):
		cam = self.camerasMgr.createCamera(props)
		#self.camerasMgr.active( props['name'] )
		self.animsMgr.createAnimation(cam, self.animations[ props['name'] ] )

	def createEntity(self,props):
		props['parent'] = self.__nodesDict[props['groupName']]

		name =  props['name']

		ent = yaml.load( self.yamlList[name] )

		model = loader.loadModel( ent.model_path )

		body = self.physicsMgr.createRigidBody(ent.physics['shapetype'],model,ent.physics)

		ent.init(model,body,props)

		self.__entitiesDict[name] = ent

		self.animsMgr.createAnimation(ent.getNode(), self.animations[name])

	def createStaticGeoms(self,props):
		path = props['configFile']

		stream = file('assets/classes/' + path + '.class', 'r')

		ent = yaml.load( stream )

		ent.init(props)

	def __del__(self):
		print 'del scene'
class GunGameLevelLoader:
    notify = directNotify.newCategory("GunGameLevelLoader")

    LevelData = {
        # momada means: Mix Of Mint And District Attorney's
        'momada': {
            'name': ZoneUtil.ToonBattleOriginalLevel,
            'camera': (Point3(0.0, -25.80, 7.59), Vec3(0.00, 0.00, 0.00)),
            'models': [
                "phase_11/models/lawbotHQ/LB_Zone03a.bam",
                "phase_11/models/lawbotHQ/LB_Zone04a.bam",
                "phase_11/models/lawbotHQ/LB_Zone7av2.bam",
                "phase_11/models/lawbotHQ/LB_Zone08a.bam",
                "phase_11/models/lawbotHQ/LB_Zone13a.bam",
                "phase_10/models/cashbotHQ/ZONE17a.bam",
                "phase_10/models/cashbotHQ/ZONE18a.bam",
                "phase_11/models/lawbotHQ/LB_Zone22a.bam"
            ],
            'parents': [
                render,
                "EXIT",
                "EXIT",
                "EXIT",
                "ENTRANCE",
                "ENTRANCE",
                "ENTRANCE",
                "EXIT"
            ],
            'model_positions': [
                Point3(0.00, 0.00, 0.00),
                Point3(-1.02, 59.73, 0.00),
                Point3(0.00, 74.77, 0.00),
                Point3(0.00, 89.37, -13.50),
                Point3(16.33, -136.53, 0.00),
                Point3(-1.01, -104.40, 0.00),
                Point3(0.65, -23.86, 0.00),
                Point3(-55.66, -29.01, 0.00)
            ],
            'model_orientations': [
                Vec3(0.00, 0.00, 0.00),
                Vec3(0.00, 0.00, 0.00),
                Vec3(90.00, 0.00, 0.00),
                Vec3(180.00, 0.00, 0.00),
                Vec3(97.00, 0.00, 0.00),
                Vec3(359.95, 0.00, 0.00),
                Vec3(90.00, 0.00, 0.00),
                Vec3(270.00, 0.00, 0.00)
            ],
            'spawn_points': [
                (Point3(0, 0, 0), Vec3(0, 0, 0)),
                (Point3(-20, 50, 0), Vec3(0, 0, 0)),
                (Point3(20, 50, 0), Vec3(0, 0, 0)),
                (Point3(0, 120, 0), Vec3(0, 0, 0)),
                (Point3(0, 100, 0), Vec3(180, 0, 0)),
                (Point3(-90, 0, 0), Vec3(0, 0, 0)),
                (Point3(-170, 0, 0), Vec3(0, 0, 0)),
                (Point3(-90, 50, 0), Vec3(0, 0, 0)),
                (Point3(-170, 50, 0), Vec3(0, 0, 0)),
                (Point3(35, 250, 0), Vec3(-90, 0, 0)),
                (Point3(0, 285, 0), Vec3(180, 0, 0)),
                (Point3(-185, 250, 0), Vec3(90, 0, 0))
            ]
        },

        'dg': {
            'name': ZoneUtil.DaisyGardens,
            'camera': (Point3(-33.13, -3.20, 48.62), Vec3(326.31, 332.68, 0.00)),
            'dna': [
                'phase_8/dna/storage_DG.pdna',
                'phase_8/dna/storage_DG_sz.pdna',
                'phase_8/dna/daisys_garden_sz.pdna'
            ],
            'sky': 'TT',
            'spawn_points': hoodMgr.dropPoints[ZoneUtil.DaisyGardens]
        },

        'mml': {
            'name': ZoneUtil.MinniesMelodyland,
            'camera': (Point3(-54.42, -91.05, 34.89), Vec3(315.29, 336.80, 0.00)),
            'dna': [
                'phase_6/dna/storage_MM.pdna',
                'phase_6/dna/storage_MM_sz.pdna',
                'phase_6/dna/minnies_melody_land_sz.pdna'
            ],
            'sky': 'MM',
            'spawn_points': hoodMgr.dropPoints[ZoneUtil.MinniesMelodyland]
        },

        'oz': {
            'name': ZoneUtil.OutdoorZone,
            'camera': (Point3(-54.42, -91.05, 34.89), Vec3(315.29, 336.80, 0.00)),
            'dna': [
                'phase_6/dna/storage_OZ.pdna',
                'phase_6/dna/storage_OZ_sz.pdna',
                'phase_6/dna/outdoor_zone_sz.pdna'
            ],
            'sky': 'TT',
            'spawn_points': hoodMgr.dropPoints[ZoneUtil.OutdoorZone]
        },

        'cbhq': {
            'name': ZoneUtil.CashbotHQ,
            'camera': (Point3(302.64, 5.00, 15.20), Vec3(135.00, 341.57, 0.00)),
            'model': 'phase_10/models/cogHQ/CashBotShippingStation.bam',
            'sky': None,
            'spawn_points': hoodMgr.dropPoints[ZoneUtil.CashbotHQ]
        },

        'sbf': {
            'name': ZoneUtil.SellbotFactory,
            'camera': (Point3(0, 0, 0), Vec3(0, 0, 0)),
            'model': "phase_9/models/cogHQ/SelbotLegFactory.bam",
            'sky': 'cog',
            'sky_scale': 10.0,
            'occluders': 'phase_9/models/cogHQ/factory_sneak_occluders.egg',
            'spawn_points': {GGG.Teams.BLUE: [
                    (Point3(13, 30, 3.73), Point3(0, 0, 0)), (Point3(21, 30, 3.73), Point3(0, 0, 0)), (Point3(29, 30, 3.73), Point3(0, 0, 0)),
                    (Point3(13, 20, 3.73), Point3(0, 0, 0)), (Point3(21, 20, 3.73), Point3(0, 0, 0)), (Point3(29, 30, 3.73), Point3(0, 0, 0))],
                GGG.Teams.RED: [
                    (Point3(-644.43, 378.12, 8.73), Point3(270, 0, 0)), (Point3(-644.43, 370.75, 8.73), Point3(270, 0, 0)), (Point3(-644.43, 363.22, 8.73), Point3(270, 0, 0)),
                    (Point3(-659.05, 378.12, 8.73), Point3(270, 0, 0)), (Point3(-659.05, 370.75, 8.73), Point3(270, 0, 0)), (Point3(-659.05, 363.22, 8.73), Point3(270, 0, 0))]
            },
            'flag_points': {GGG.Teams.BLUE: [Point3(213.23, 340.59, 19.73), Point3(90, 0, 0)],
                GGG.Teams.RED: [Point3(-543.60, 595.79, 9.73), Point3(270, 0, 0)]},
            'flagpoint_points': {GGG.Teams.BLUE: [Point3(-543.60, 595.79, 9.73), Point3(270, 0, 0)],
                GGG.Teams.RED: [Point3(213.23, 340.59, 19.73), Point3(0, 0, 0)]}
        },
        
        'ttc' : {
            'name' : ZoneUtil.ToontownCentral,
            'dna' : [
                'phase_4/dna/storage_TT.pdna',
                'phase_4/dna/storage_TT_sz.pdna',
                'phase_4/dna/new_ttc_sz.pdna',
            ],
            'sky' : 'TT',
            'spawn_points' : [
                (9.90324401855, 91.9139556885, 8.0364112854, -545.909545898, 0.0, 0.0),
                (77.9181442261, 50.953086853, 7.52815723419, -598.509460449, 0.0, 0.0),
                (93.7379760742, 6.37303066254, 7.99749088287, -626.209533691, 0.0, 0.0),
                (39.0383415222, -81.5989837646, 8.01874637604, -694.309265137, 0.0, 0.0),
                (-19.2093048096, -95.1359481812, 8.07303524017,  -731.409240723, 0.0, 0.0),
                (-84.4093933105, -45.4780502319, 8.06541728973, -781.809143066, 0.0, 0.0),
                (-92.2512283325, 2.41426730156, 8.03108692169, -811.70916748, 0.0, 0.0),
                (46.8868179321, 81.3593673706, 8.04793071747, -955.309509277, 0.0, 0.0),
                (32.3203735352, 90.0017929077, 8.06353855133, -884.409301758, 0.0, 0.0)
            ],
            'cap_point' : Point3(-1.5, 0, 0)
        }
    }

    SkyData = {
        'TT': 'phase_3.5/models/props',
        'MM': 'phase_6/models/props',
        'cog': 'phase_9/models/cogHQ',

        'MovingSkies': ['TT']
    }

    def __init__(self, mg):
        self.mg = mg
        self.levelName = None
        self.dnaStore = DNAStorage()
        self.loadingText = None

        # for not momada only:
        self.levelGeom = None
        self.olc = None
        self.occluders = None

        # for momada only:
        self.momadaAreas = []
        self.momadaAreaName2areaModel = {}

    def getFlagPoint_Point(self, team):
        return self.LevelData[self.levelName]['flagpoint_points'][team]

    def getFlagPoint(self, team):
        return self.LevelData[self.levelName]['flag_points'][team]
    
    def getCapturePoint(self):
        return self.LevelData[self.levelName]['cap_point']

    def setLevel(self, level):
        self.levelName = level

    def getLevel(self):
        return self.levelName

    def getCameraOfCurrentLevel(self):
        return self.LevelData[self.getLevel()]['camera']

    def getSpawnPoints(self):
        # Return the spawn points for this level.
        pointData = self.LevelData[self.levelName]['spawn_points']
        if self.levelName == "momada":
            return pointData
        else:
            if self.mg.gameMode in [GGG.GameModes.CASUAL, GGG.GameModes.KOTH]:
                # These points come from src.coginvasion.distributed.HoodMgr,
                # which is a tuple of a bunch of arrays with pos as first
                # 3, and hpr as last 3 list elements.
                #
                # Disect the arrays and return a tuple holding a Point3 pos, and a Vec3 hpr.
                array = []
                for posAndHpr in pointData:
                    array.append(
                        (
                            Point3(
                                posAndHpr[0],
                                posAndHpr[1],
                                posAndHpr[2]
                            ),

                            Vec3(
                                posAndHpr[3],
                                posAndHpr[4],
                                posAndHpr[5]
                            )
                        )
                    )
            elif self.mg.gameMode == GGG.GameModes.CTF:
                array = pointData[self.mg.team]
            return array

    def getNameOfCurrentLevel(self):
        return self.LevelData[self.getLevel()]['name']

    def load(self):
        self.unload()
        if self.loadingText:
            self.loadingText.destroy()
            self.loadingText = None
        self.loadingText = OnscreenText(text = "",
            font = CIGlobals.getMinnieFont(), fg = (1, 1, 1, 1))
        self.loadingText.setBin('gui-popup', 0)
        base.graphicsEngine.renderFrame()
        base.graphicsEngine.renderFrame()
        if self.levelName == "momada":
            # momada is completely different from the other levels,
            # so it has it's own separate method for loading.
            self.__momadaLoad()
        elif self.levelName in ['cbhq', 'sbf']:
            # Cog hqs are just one model with everything in it. no dna loading needed.
            modelPath = self.LevelData[self.levelName]['model']
            self.levelGeom = loader.loadModel(modelPath)
            self.levelGeom.flattenMedium()
            self.levelGeom.reparentTo(render)
            if self.LevelData[self.levelName].get('occluders'):
                self.occluders = loader.loadModel(self.LevelData[self.levelName]['occluders'])
                for occluderNode in self.occluders.findAllMatches('**/+OccluderNode'):
                    base.render.setOccluder(occluderNode)
                    occluderNode.node().setDoubleSided(True)
            if self.levelName == 'sbf':
                base.camLens.setFar(250)
        else:
            # It's a playground with dna and stuff. Just do the
            # normal loading procedure.
            dnaFiles = self.LevelData[self.levelName]['dna']
            loadDNAFile(self.dnaStore, 'phase_4/dna/storage.pdna')
            for index in range(len(dnaFiles)):
                if index == len(dnaFiles) - 1:
                    node = loadDNAFile(self.dnaStore, dnaFiles[index])
                    if node.getNumParents() == 1:
                        self.levelGeom = NodePath(node.getParent(0))
                        self.levelGeom.reparentTo(hidden)
                    else:
                        self.levelGeom = hidden.attachNewNode(node)
                    if self.levelName == 'ttc' and dnaFiles[index] == 'phase_4/dna/new_ttc_sz.pdna':
                        self.levelGeom.find('**/prop_gazebo_DNARoot').removeNode()
                    else:
                        self.levelGeom.flattenMedium()
                    gsg = base.win.getGsg()
                    if gsg:
                        self.levelGeom.prepareScene(gsg)
                    self.levelGeom.reparentTo(render)
                else:
                    loadDNAFile(self.dnaStore, dnaFiles[index])
            children = self.levelGeom.findAllMatches('**/*doorFrameHole*')
            
            for child in children:
                child.hide()

        self.olc = ZoneUtil.getOutdoorLightingConfig(self.LevelData[self.levelName].get('name'))
        self.olc.setupAndApply()

        if self.loadingText:
            self.loadingText.destroy()
            self.loadingText = None

    def __momadaLoad(self):

        def attachArea(itemNum):
            name = 'MomadaArea-%s' % itemNum
            area = self.momadaAreaName2areaModel.get(name)
            parents = self.LevelData['momada']['parents']
            parent = parents[itemNum]
            if type(parent) == type(""):
                parent = self.momadaAreas[itemNum - 1].find('**/' + parent)
            pos = self.LevelData['momada']['model_positions'][itemNum]
            hpr = self.LevelData['momada']['model_orientations'][itemNum]
            area.reparentTo(parent)
            area.setPos(pos)
            area.setHpr(hpr)

        _numItems = 0
        name = None
        for item in self.LevelData['momada']['models']:
            name = 'MomadaArea-%s' % _numItems
            area = loader.loadModel(item)
            self.momadaAreas.append(area)
            self.momadaAreaName2areaModel[name] = area
            attachArea(_numItems)
            _numItems += 1
            self.notify.info("Loaded and attached %s momada areas." % _numItems)

    def unload(self):
        render.clearOccluder()
        if self.olc:
            self.olc.cleanup()
            self.olc = None
        if self.levelName == "sbf":
            base.camLens.setFar(CIGlobals.DefaultCameraFar)
        if self.levelName == "momada":
            for area in self.momadaAreas:
                self.momadaAreas.remove(area)
                area.removeNode()
                del area
            self.momadaAreas = []
            self.momadaAreaName2areaModel = {}
        else:
            if self.occluders:
                self.occluders.removeNode()
                self.occluders = None
            if self.levelGeom:
                self.levelGeom.removeNode()
                self.levelGeom = None

    def cleanup(self):
        self.momadaAreas = None
        self.momadaAreaName2areaModel = None
        if self.dnaStore:
            self.dnaStore.reset_nodes()
            self.dnaStore.reset_hood_nodes()
            self.dnaStore.reset_place_nodes()
            self.dnaStore.reset_hood()
            self.dnaStore.reset_fonts()
            self.dnaStore.reset_DNA_vis_groups()
            self.dnaStore.reset_materials()
            self.dnaStore.reset_block_numbers()
            self.dnaStore.reset_block_zones()
            self.dnaStore.reset_suit_points()
        self.dnaStore = None
Пример #14
0
class TTCHood:
    
    def __init__(self, cr):
        self.cr = cr
        self.dnaStore = DNAStorage()
        self.isLoaded = 0
        self.suitEffectEnabled = False
        self.amblight = None
        self.ambNode = None
        self.sky = None
        self.skyTrack = None
        self.skySeq = None
        self.lightTrack = None
        self.skyUtil = SkyUtil()
        
    def createHood(self, loadStorage = 1, AI = 0):
        if loadStorage:
            loadDNAFile(self.dnaStore, "phase_4/dna/storage.dna")
            loadDNAFile(self.dnaStore, "phase_4/dna/storage_TT.dna")
            loadDNAFile(self.dnaStore, "phase_4/dna/storage_TT_sz.dna")
            loadDNAFile(self.dnaStore, "phase_5/dna/storage_town.dna")
            loadDNAFile(self.dnaStore, "phase_5/dna/storage_TT_town.dna")
        self.node = loadDNAFile(self.dnaStore, "phase_4/dna/toontown_central_sz.dna")
        if self.node.getNumParents() == 1:
            self.geom = NodePath(self.node.getParent(0))
            self.geom.reparentTo(hidden)
        else:
            self.geom = hidden.attachNewNode(self.node)
        gsg = base.win.getGsg()
        if gsg:
            self.geom.prepareScene(gsg)
        self.geom.setName('toontown_central')
        
        self.geom.find('**/hill').setTransparency(TransparencyAttrib.MBinary, 1)
        self.createSky("tt")
        base.hoodBGM = base.loadMusic("phase_4/audio/bgm/TC_nbrhood.ogg")
        base.hoodBGM.setVolume(0.25)
        base.hoodBGM.setLoop(True)
        base.hoodBGM.play()
        
        self.clerk_node = render.attach_new_node('clerk_node')
        self.clerk_node.set_pos(-80, -85.57, 0.5)
        self.clerk_node.set_h(165.07)
        
        self.geom.find('**/toontown_central').setCollideMask(BitMask32.allOff())
        self.geom.find('**/coll_sidewalk').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/collision_1').node().setIntoCollideMask(CIGlobals.WallBitmask)
        self.geom.find('**/coll_mainFoolr').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/left_ear').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/right_ear').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_bridge_floor').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_bridge').node().setIntoCollideMask(CIGlobals.WallBitmask)
        self.geom.find('**/coll_r_stair').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_l_stair_2').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_l_stairend_1').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_r_satirend_1').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_plaza').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_hedges').node().setIntoCollideMask(CIGlobals.WallBitmask)
        
        self.coll_list = ['coll_sidewalk', 'collision_1', 'coll_mainFoolr', 'left_ear', 'right_ear', 'coll_bridge_floor', 'coll_bridge', 'coll_r_stair',
                        'coll_l_stair_2', 'coll_l_stairend_1', 'coll_r_stairend_1', 'coll_plaza', 'coll_hedges']
        self.geom.reparentTo(render)
        
        self.telescope = Actor(self.geom.find('**/*animated_prop_HQTelescopeAnimatedProp*'),
                            {"chan": "phase_3.5/models/props/HQ_telescope-chan.bam"}, copy=0)
        self.telescope.reparentTo(self.geom.find('**/*toon_landmark_hqTT*'))
        self.createLights(1, 1, 1)
        
        #if AI:
        #    self.createTrolley()
        
        taskMgr.add(self.telescopeTask, "telescopeTask")
        self.isLoaded = 1
        messenger.send("loadedHood")
        
    def createLights(self, r, g, b, startColor=1, fade=0):
        self.deleteLights()
        self.amblight = AmbientLight("amblight")
        self.amblight.setColor(VBase4(r, g, b, 1))
        self.ambNode = render.attachNewNode(self.amblight)
        render.setLight(self.ambNode)
        if fade:
            self.lightTrack = LerpFunc(self.setLightColor,
                                fromData=startColor,
                                toData=r,
                                duration=2.5,
                                blendType="easeInOut")
            self.lightTrack.start()
            self.skyTrack = LerpColorInterval(self.sky,
                                        color=VBase4(r + 0.4, g + 0.4, b + 0.4, 1.0),
                                        startColor=VBase4(startColor, startColor, startColor, 1.0),
                                        duration=1.5)
            self.skyTrack.start()
            sky = "tt"
            if r < 0.6:
                sky = "br"
            self.skySeq = Sequence(Wait(1.5), Func(self.createSky, sky))
            self.skySeq.start()
            
    def createSky(self, sky):
        self.deleteSky()
        skyPath = "phase_3.5/models/props/" + sky.upper() + "_sky.bam"
        self.sky = loader.loadModel(skyPath)
        self.sky.reparentTo(self.geom)
        self.sky.setPos(9.15527e-005, -1.90735e-006, 2.6226e-006)
        self.sky.setH(-90)
        if sky == "tt":
            self.skyUtil.startSky(self.sky)
            
    def deleteSky(self):
        self.skyUtil.stopSky()
        if self.sky:
            self.sky.removeNode()
            self.sky = None
        if self.lightTrack:
            self.lightTrack.pause()
            self.lightTrack = None
        if self.skyTrack:
            self.skyTrack.pause()
            self.skyTrack = None
        if self.skySeq:
            self.skySeq.pause()
            self.skySeq = None
            
    def setLightColor(self, color):
        self.amblight.setColor(VBase4(color, color, color, 1))
        
    def deleteLights(self):
        if self.ambNode:
            render.clearLight(self.ambNode)
            self.ambNode.removeNode()
            self.ambNode = None
        
    def telescopeTask(self, task):
        if not self.isLoaded:
            return task.done
        self.telescope.play("chan")
        task.delayTime = 12
        return task.again
        
    def enableSuitEffect(self, size):
        self.createLights(0.4, 0.4, 0.4, startColor=1, fade=1)
        
        self.fogNode = Fog("fog")
        self.fogNode.setColor(0.3, 0.3, 0.3)
        self.fogNode.setExpDensity(0.0025)
        render.setFog(self.fogNode)
        
        base.hoodBGM.stop()
        song = random.randint(1, 4)
        base.hoodBGM = base.loadMusic("phase_3.5/audio/bgm/encntr_general_bg.ogg")
        base.hoodBGM.setVolume(0.7)
        base.hoodBGM.setLoop(True)
        base.hoodBGM.play()
        
        self.suitEffectEnabled = True
        
    def bossSpawned(self):
        base.hoodBGM.stop()
        base.hoodBGM = base.loadMusic("phase_7/audio/bgm/encntr_suit_winning_indoor.ogg")
        base.hoodBGM.setVolume(0.7)
        base.hoodBGM.setLoop(True)
        Sequence(Wait(0.5), Func(base.hoodBGM.play)).start()
        
    def disableSuitEffect(self):
        self.createLights(1, 1, 1)
        self.createSky("tt")
        #render.clearFog()
        
        base.hoodBGM.stop()
        base.hoodBGM = base.loadMusic("phase_4/audio/bgm/TC_nbrhood.ogg")
        base.hoodBGM.setVolume(0.25)
        base.hoodBGM.setLoop(True)
        base.hoodBGM.play()
        
        self.suitEffectEnabled = False
        
    def unloadHood(self):
        self.isLoaded = 0
        if self.suitEffectEnabled:
            self.disableSuitEffect()
        self.deleteSky()
        self.deleteLights()
        self.geom.remove()
        self.clerk_node.remove_node()
        base.hoodBGM.stop()
class HomeHood:
    dnaStore = DNAStorage()

    def createHood(self, loadStorage=1):
        self.isLoaded = 0
        if loadStorage:
            loadDNAFile(self.dnaStore, "phase_5.5/dna/storage_estate.dna")
        node = loadDNAFile(self.dnaStore, "phase_5.5/dna/estate_1.dna")
        if node.getNumParents() == 1:
            self.geom = NodePath(node.getParent(0))
            self.geom.reparentTo(hidden)
        else:
            self.geom = hidden.attachNewNode(self.node)
        gsg = base.win.getGsg()
        if gsg:
            self.geom.prepareScene(gsg)
        self.geom.setName('home')

        self.geom.find('**/Path').setTransparency(TransparencyAttrib.MBinary,
                                                  1)

        self.sky = loader.loadModel("phase_3.5/models/props/TT_sky.bam")
        self.sky.reparentTo(self.geom)
        self.sky.setPos(-4.99989, -0.000152588, 2.28882e-005)

        self.geom.find('**/terrain').setCollideMask(BitMask32.allOff())
        self.geom.find('**/terrain_barrier').node().setIntoCollideMask(
            CIGlobals.WallBitmask)
        self.geom.find("**/collision_fence").node().setIntoCollideMask(
            CIGlobals.WallBitmask)
        self.geom.find('**/collision4').node().setIntoCollideMask(
            CIGlobals.FloorBitmask)
        self.geom.find("**/collision3").node().setIntoCollideMask(
            CIGlobals.FloorBitmask)
        self.geom.find("**/collision1").node().setIntoCollideMask(
            CIGlobals.FloorBitmask)

        self.geom.reparentTo(render)

        messenger.send("loadedHood")

        self.skyUtil = SkyUtil()
        self.skyUtil.startSky(self.sky)

        self.isLoaded = 1

    def unloadHood(self):
        self.skyUtil.stopSky()
        self.geom.remove()
        self.isLoaded = 0
class SafeZoneLoader(StateData):
    notify = directNotify.newCategory("SafeZoneLoader")

    def __init__(self, hood, parentFSMState, doneEvent):
        StateData.__init__(self, doneEvent)
        self.hood = hood
        self.parentFSMState = parentFSMState
        self.fsm = ClassicFSM('safeZoneLoader', [
            State('off', self.enterOff, self.exitOff),
            State('playground', self.enterPlayground, self.exitPlayground,
                  ['quietZone']),
            State('toonInterior', self.enterToonInterior,
                  self.exitToonInterior, ['quietZone']),
            State('quietZone', self.enterQuietZone, self.exitQuietZone,
                  ['playground', 'toonInterior'])
        ], 'off', 'off')
        self.placeDoneEvent = 'placeDone'
        self.place = None
        self.playground = None
        self.nodeList = []
        self.linkTunnels = []
        self.szHolidayDNAFile = None
        self.animatedFish = None
        self.safeZoneSong = ''
        self.interiorSong = ''
        return

    def doBaseOptimizations(self):
        # Performs base optimizations that all playgrounds can benefit from.
        # Combines all flat walls together, optimizes all landmark buildings,
        # tunnels, trees, fishing docks.
        #
        # Any optimizations for a specific playground should be done in
        # doFlatten() in that playground's SafeZoneLoader.

        flats = self.geom.attachNewNode('flats')
        for np in self.geom.findAllMatches("**/sz0:*_DNARoot"):
            np.wrtReparentTo(flats)
        for np in self.geom.findAllMatches("**/tb0:*_DNARoot"):
            np.wrtReparentTo(flats)
        for np in self.geom.findAllMatches("**/*random*_DNARoot"):
            np.wrtReparentTo(flats)
        CIGlobals.removeDNACodes(flats)
        flats.clearModelNodes()
        flats.flattenStrong()
        CIGlobals.moveChildren(flats, self.geom)

        tunnels = self.geom.findAllMatches("**/*linktunnel*")
        for tunnel in tunnels:
            tunnel.flattenStrong()

        for landmark in self.geom.findAllMatches("**/*toon_landmark*_DNARoot"):
            CIGlobals.removeDNACodes(landmark)
            landmark.flattenStrong()

        signs = self.geom.attachNewNode("signs")
        CIGlobals.moveNodes(self.geom, "*neighborhood_sign*_DNARoot", signs)
        #for sign in signs.getChildren():
        #sign.clearTransform()
        CIGlobals.removeDNACodes(signs)
        signs.clearModelNodes()
        signs.flattenStrong()
        CIGlobals.moveChildren(signs, self.geom)

        fish = self.geom.attachNewNode("fishspots")
        CIGlobals.moveNodes(self.geom, "fishing_spot_DNARoot", fish)
        CIGlobals.removeDNACodes(fish)
        fish.clearModelNodes()
        fish.flattenStrong()
        CIGlobals.moveChildren(fish, self.geom)

        trees = self.geom.attachNewNode("trees")
        for np in self.geom.findAllMatches("**/*prop_tree*_DNARoot"):
            np.wrtReparentTo(trees)
        CIGlobals.removeDNACodes(trees)
        trees.clearModelNodes()
        trees.flattenStrong()
        CIGlobals.moveChildren(trees, self.geom)

    def findAndMakeLinkTunnels(self):
        for tunnel in self.geom.findAllMatches('**/*linktunnel*'):
            dnaRootStr = tunnel.getName()
            link = LinkTunnel.SafeZoneLinkTunnel(tunnel, dnaRootStr)
            self.linkTunnels.append(link)

    def load(self, flattenNow=True):
        StateData.load(self)

        self.createSafeZone(self.dnaFile, flattenNow)

        children = self.geom.findAllMatches('**/*doorFrameHole*')

        for child in children:
            child.hide()

        self.parentFSMState.addChild(self.fsm)

    def unload(self):
        StateData.unload(self)

        base.waterReflectionMgr.clearWaterNodes()

        if self.animatedFish:
            self.animatedFish.cleanup()
            self.animatedFish.removeNode()
            self.animatedFish = None

        if self.linkTunnels is not None:
            for link in self.linkTunnels:
                link.cleanup()
        self.linkTunnels = None
        if self.nodeList is not None:
            for node in self.nodeList:
                node.removeNode()
        self.nodeList = None

        self.parentFSMState.removeChild(self.fsm)
        del self.parentFSMState
        del self.animatedFish
        base.disableAndRemovePhysicsNodes(self.geom)
        self.geom.removeNode()
        del self.geom
        del self.fsm
        del self.hood
        del self.playground
        del self.safeZoneSong
        del self.interiorSong
        self.ignoreAll()

        #CIGlobals.doSceneCleanup()

    def enter(self, requestStatus):
        StateData.enter(self)
        if base.localAvatar.zoneId < ZoneUtil.DynamicZonesBegin:
            self.findAndMakeLinkTunnels()
        self.fsm.enterInitialState()
        messenger.send('enterSafeZone')
        self.setState(requestStatus['where'], requestStatus)
        # Delete party gate
        partyGate = self.geom.find('**/prop_party_gate_DNARoot')
        if not partyGate.isEmpty():
            partyGate.removeNode()
        del partyGate
        # Delete pet shop
        petShop = self.geom.find('**/*pet_shop_DNARoot*')
        if not petShop.isEmpty():
            fish = petShop.find(
                '**/animated_prop_PetShopFishAnimatedProp_DNARoot')
            if fish:
                """
                self.animatedFish = Actor('phase_4/models/props/exteriorfish-zero.bam', {'chan' :
                    'phase_4/models/props/exteriorfish-swim.bam'})
                #self.animatedFish.reparentTo(hidden)#petShop)
                #self.animatedFish.setPos(fish.getPos())
                #self.animatedFish.loop('chan')
                #self.animatedFish.cleanup()
                """
                fish.removeNode()
            #petShop.removeNode()
        #del petShop

        CIGlobals.preRenderScene(self.geom)

    def exit(self):
        StateData.exit(self)
        messenger.send('exitSafeZone')
        for link in self.linkTunnels:
            link.cleanup()
        if self.animatedFish:
            self.animatedFish.stop('chan')
        self.linkTunnels = []

    def setState(self, stateName, requestStatus):
        self.fsm.request(stateName, [requestStatus])

    def createSafeZone(self, dnaFile, flattenNow=True):
        if self.szStorageDNAFile:
            if isinstance(self.szStorageDNAFile, list):
                # We are loading multiple sz storages.
                for i in xrange(len(self.szStorageDNAFile)):
                    loader.loadDNAFile(self.hood.dnaStore,
                                       self.szStorageDNAFile[i])
            else:
                loader.loadDNAFile(self.hood.dnaStore, self.szStorageDNAFile)

        if self.szHolidayDNAFile:
            loader.loadDNAFile(self.hood.dnaStore, self.szHolidayDNAFile)

        node = loader.loadDNAFile(self.hood.dnaStore, dnaFile)
        if node.getNumParents() == 1:
            self.geom = NodePath(node.getParent(0))
            self.geom.reparentTo(hidden)
        else:
            self.geom = hidden.attachNewNode(node)
        CIGlobals.replaceDecalEffectsWithDepthOffsetAttrib(self.geom)
        if flattenNow:
            self.doFlatten()
        base.createPhysicsNodes(self.geom)
        CIGlobals.preRenderScene(self.geom)

    def doFlatten(self):
        self.doBaseOptimizations()
        self.makeDictionaries(self.hood.dnaStore)
        self.geom.flattenMedium()

    def makeDictionaries(self, dnaStore):
        self.nodeList = []
        for i in xrange(dnaStore.getNumDNAVisGroups()):
            groupFullName = dnaStore.getDNAVisGroupName(i)
            #groupName = base.cr.hoodMgr.extractGroupName(groupFullName)
            groupNode = self.geom.find('**/' + groupFullName)
            if groupNode.isEmpty():
                self.notify.error('Could not find visgroup')
            groupNode.flattenMedium()
            self.nodeList.append(groupNode)

        self.hood.dnaStore.resetPlaceNodes()
        self.hood.dnaStore.resetDNAGroups()
        self.hood.dnaStore.resetDNAVisGroups()
        self.hood.dnaStore.resetDNAVisGroupsAI()

    def enterPlayground(self, requestStatus):
        try:
            self.hood.stopSuitEffect()
        except:
            pass
        self.acceptOnce(self.placeDoneEvent, self.handlePlaygroundDone)
        self.place = self.playground(self, self.fsm, self.placeDoneEvent)
        self.place.load()

    def exitPlayground(self):
        self.ignore(self.placeDoneEvent)
        self.place.exit()
        self.place.unload()
        self.place = None
        base.cr.playGame.setPlace(self.place)
        return

    def handlePlaygroundDone(self):
        status = self.place.doneStatus
        if self.hood.isSameHood(status) and status[
                'loader'] == 'safeZoneLoader' and not status['where'] in [
                    'minigame'
                ]:
            self.fsm.request('quietZone', [status])
        else:
            self.doneStatus = status
            messenger.send(self.doneEvent)
        return

    def enterToonInterior(self, requestStatus):
        self.acceptOnce(self.placeDoneEvent, self.handleToonInteriorDone)
        self.place = ToonInterior.ToonInterior(self, self.fsm,
                                               self.placeDoneEvent)
        self.place.load()

    def enterThePlace(self, requestStatus):
        base.cr.playGame.setPlace(self.place)
        if self.place is not None:
            self.place.enter(requestStatus)

    def exitToonInterior(self):
        self.ignore(self.placeDoneEvent)
        self.place.exit()
        self.place.unload()
        self.place = None
        base.cr.playGame.setPlace(self.place)
        return

    def handleToonInteriorDone(self):
        status = self.place.doneStatus
        if (status['loader'] == 'safeZoneLoader'
                and self.hood.isSameHood(status) and status['shardId'] is None
                or status['how'] == 'doorOut'):
            self.fsm.request('quietZone', [status])
        else:
            self.doneStatus = status
            messenger.send(self.doneEvent)
        return

    def enterQuietZone(self, requestStatus):
        self.fsm.request(requestStatus['where'], [requestStatus],
                         exitCurrent=0)

        self.quietZoneDoneEvent = uniqueName('quietZoneDone')
        self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone)
        self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent)
        self.quietZoneStateData.load()
        self.quietZoneStateData.enter(requestStatus)

    def exitQuietZone(self):
        self.ignore(self.quietZoneDoneEvent)
        del self.quietZoneDoneEvent
        self.quietZoneStateData.exit()
        self.quietZoneStateData.unload()
        self.quietZoneStateData = None
        return

    def handleQuietZoneDone(self):
        status = self.quietZoneStateData.getDoneStatus()
        self.exitQuietZone()
        if status['where'] == 'estate' or status['loader'] == 'townLoader':
            self.doneStatus = status
            messenger.send(self.doneEvent)
        else:
            self.enterThePlace(status)

    def enterOff(self):
        pass

    def exitOff(self):
        pass
Пример #17
0
class EnemySegment():
    def __init__(self, geometry, length=0, x=0, y=0, following=None):
        self.node = NodePath("segment")
        geometry.copy_to(self.node)
        self.node.reparent_to(render)
        self.node.set_y(100 + y)
        self.node.set_x(x)
        self.following = following
        self.follower = None
        if length > 0:
            self.follower = EnemySegment(geometry,
                                         length=length - 1,
                                         x=x,
                                         y=y + 1,
                                         following=self)
            base.segments.append(self.follower)
        self.angle = 180
        self.head = self.node.find("**/head*")
        self.mid = self.node.find("**/mid*")
        self.tail = self.node.find("**/tail*")
        self.ouch = 0

    def destroy(self, zapped=False):
        Explosion(base.models["misc"]["explosion_a"],
                  self.node.get_pos(),
                  speed=uniform(1, 2))
        if self.following:
            if not zapped:
                Mine(self.node.get_pos())
            self.following.follower = None
        if self.follower:
            if base.flower_time[0] >= base.flower_time[1]:
                if not base.player.flowerpower > 0:
                    Flower(self.node.get_pos())
                    base.flower_time[0] = 0
            if not self.following:
                self.follower.ouch = 0.3
            else:
                self.follower.angle += randint(-45, 45)
            self.follower.following = None
        base.segments.remove(self)
        self.node.remove_node()

    def update(self):
        dt = globalClock.get_dt()
        if self.ouch > 0:
            self.ouch -= dt
        self.head.hide()
        self.mid.hide()
        self.tail.hide()
        if self.following:
            self.node.set_pos(self.following.node.get_pos())
            if self.follower: self.mid.show()
            else: self.tail.show()
            self.angle = self.following.angle
            self.node.set_h(self.following.angle)
        else:
            self.head.show()
            if randint(0, 16) == 0 and self.ouch <= 0:
                self.angle += randint(-45, 45)
            self.node.set_h(self.angle)
            self.node.set_pos(self.node, (0, 1, 0))
            x, y, z = self.node.get_pos()
            xsize, ysize = base.map_size
            if x < -xsize or x > xsize or y < 0 or y > ysize:
                base.sounds["2d"]["bounce"].play()
                self.angle += 180 + randint(-45, 45)
            limit_node(self.node)

        vector = base.player.node.getPos() - self.node.getPos()
        distance = vector.get_xy().length()
        if distance < 0.8:
            base.player.die()