예제 #1
0
 def attachNewCollidableNode( self, node, bitmask=None ):
   if bitmask is None:
     bitmask = self.bitmask
   # attach a new node which is colliable
   NodePath.attachNewNode( self, node )
   self.setTag('objectId', self.objectId )
   self.setCollideMask( bitMaskOr(bitmask) )
예제 #2
0
class SimViewer(LightBase):
    """ Visualizes simulation."""
    def __init__(self):
        super(SimViewer, self).__init__()
        # Make a window.
        size = (700, 520)
        self.create_output(size, "SimViewer")
        self.output.setClearColor((0.0, 0.0, 0.0, 1.0))
        # Lights node
        self.lights = NodePath('lights')
        # Create a spotlight
        slight = Spotlight('slight')
        slight.setScene(self.root)
        slight.setShadowCaster(True, 2**11, 2**11)
        # Set shadow mask, so we can exclude objects from casting shadows
        self.shadow_mask = BitMask32.bit(2)
        slight.setCameraMask(self.shadow_mask)
        c = 1.4
        slight.setColor((c, c, c, 1.0))
        slight.getLens().setNearFar(4, 100)
        slight.getLens().setFov(45)
        slnp = self.lights.attachNewNode(slight)
        slnp.setPos((7, 10, 40))
        slnp.lookAt(2, 0, 1.5)
        self.root.setLight(slnp)
        # Create an ambient light.
        alight = AmbientLight('alight')
        c = 0.6
        alight.setColor((c, c, c, 1.0))
        alnp = self.lights.attachNewNode(alight)
        self.root.setLight(alnp)
        self.lights.reparentTo(self.root)
        # Set auto shading for shadows.
        self.root.setShaderAuto()
        # Set antialiasing on.
        self.root.setAntialias(AntialiasAttrib.MAuto)
        # Camera.
        lens = PerspectiveLens()
        self.lens = lens
        self.lens.setNearFar(0.1, 1000.)
        self.lens.setFov((40, 30))
        self.cameras = self.root.attachNewNode('cameras')
        self.camera = self.make_camera(self.output, lens=self.lens)
        self.camera.setPos(15, 44, 3.)
        self.camera.setPos(15, 35, 15.)
        self.camera.lookAt(0, 0, 1.)

    def create_output(self, size, name):
        self.output = self.make_window(size=size, name=name)
        self.render_frame()
        self.render_frame()
예제 #3
0
def setupWheel():
    global wheel
    model = loader.loadModel("models/shipparts/pir_m_shp_prt_wheel")
    wheel = NodePath("wheelRoot")
    r = model.find("**/+LODNode")
    r.flattenStrong()
    collisions = model.find("**/collisions")
    high = r.find("**/lod_high")
    med = r.find("**/lod_med")
    low = r.find("**/lod_low")
    high.reparentTo(wheel.attachNewNode(ModelNode("high")))
    med.reparentTo(wheel.attachNewNode(ModelNode("med")))
    low.reparentTo(wheel.attachNewNode(ModelNode("low")))
    collisions.reparentTo(wheel)
def setupWheel():
    global wheel
    model = loader.loadModel('models/shipparts/pir_m_shp_prt_wheel')
    wheel = NodePath('wheelRoot')
    r = model.find('**/+LODNode')
    r.flattenStrong()
    collisions = model.find('**/collisions')
    high = r.find('**/lod_high')
    med = r.find('**/lod_med')
    low = r.find('**/lod_low')
    high.reparentTo(wheel.attachNewNode(ModelNode('high')))
    med.reparentTo(wheel.attachNewNode(ModelNode('med')))
    low.reparentTo(wheel.attachNewNode(ModelNode('low')))
    collisions.reparentTo(wheel)
def setupWheel():
    global wheel
    model = loader.loadModel('models/shipparts/pir_m_shp_prt_wheel')
    wheel = NodePath('wheelRoot')
    r = model.find('**/+LODNode')
    r.flattenStrong()
    collisions = model.find('**/collisions')
    high = r.find('**/lod_high')
    med = r.find('**/lod_med')
    low = r.find('**/lod_low')
    high.reparentTo(wheel.attachNewNode(ModelNode('high')))
    med.reparentTo(wheel.attachNewNode(ModelNode('med')))
    low.reparentTo(wheel.attachNewNode(ModelNode('low')))
    collisions.reparentTo(wheel)
예제 #6
0
 def getAIShip(self, shipClass):
     ShipAI = ShipAI
     import pirates.ship
     modelClass = ShipGlobals.getModelClass(shipClass)
     hull = self.getHull(modelClass, 0)
     root = NodePath('Ship')
     collisions = root.attachNewNode('collisions')
     mastSetup = ShipGlobals.getMastSetup(shipClass)
     for data in [
         (0, 'location_mainmast_0'),
         (1, 'location_mainmast_1'),
         (2, 'location_mainmast_2'),
         (3, 'location_aftmast*'),
         (4, 'location_foremast*')]:
         mastData = mastSetup.get(data[0])
         if mastData:
             mast = self.mastSets[mastData[0]].getMastSet(mastData[1] - 1)
             model = NodePath(mast.charRoot)
             model.setPos(hull.locators.find('**/%s' % data[1]).getPos(hull.locators))
             model.setHpr(hull.locators.find('**/%s' % data[1]).getHpr(hull.locators))
             model.setScale(hull.locators.find('**/%s' % data[1]).getScale(hull.locators))
             if modelClass > ShipGlobals.INTERCEPTORL3 or data[0] != 3:
                 mastCode = str(data[0])
             else:
                 mastCode = '0'
             mast.collisions.find('**/collision_masts').setTag('Mast Code', mastCode)
             collisions.node().stealChildren(mast.collisions.node())
             continue
     
     collisions.node().stealChildren(hull.collisions.node())
     hull.locators.reparentTo(root)
     ship = ShipAI.ShipAI(root, collisions, hull.locators)
     ship.modelRoot.setTag('Mast Code', str(255))
     ship.modelRoot.setTag('Hull Code', str(255))
     return ship
    def renderQuadInto(self,
                       mul=1,
                       div=1,
                       align=1,
                       depthtex=None,
                       colortex=None,
                       auxtex0=None,
                       auxtex1=None):
        texgroup = (depthtex, colortex, auxtex0, auxtex1)
        (winx, winy) = self.getScaledSize(mul, div, align)
        depthbits = bool(depthtex != None)
        buffer = self.createBuffer('filter-stage', winx, winy, texgroup,
                                   depthbits)
        if buffer == None:
            return None

        cm = CardMaker('filter-stage-quad')
        cm.setFrameFullscreenQuad()
        quad = NodePath(cm.generate())
        quad.setDepthTest(0)
        quad.setDepthWrite(0)
        quad.setColor(Vec4(1, 0.5, 0.5, 1))
        quadcamnode = Camera('filter-quad-cam')
        lens = OrthographicLens()
        lens.setFilmSize(2, 2)
        lens.setFilmOffset(0, 0)
        lens.setNearFar(-1000, 1000)
        quadcamnode.setLens(lens)
        quadcam = quad.attachNewNode(quadcamnode)
        buffer.getDisplayRegion(0).setCamera(quadcam)
        buffer.getDisplayRegion(0).setActive(1)
        self.buffers.append(buffer)
        self.sizes.append((mul, div, align))
        return quad
    def renderSceneInto(self,
                        depthtex=None,
                        colortex=None,
                        auxtex=None,
                        auxbits=0,
                        textures=None):
        if textures:
            colortex = textures.get('color', None)
            depthtex = textures.get('depth', None)
            auxtex = textures.get('aux', None)

        if colortex == None:
            colortex = Texture('filter-base-color')
            colortex.setWrapU(Texture.WMClamp)
            colortex.setWrapV(Texture.WMClamp)

        texgroup = (depthtex, colortex, auxtex, None)
        (winx, winy) = self.getScaledSize(1, 1, 1)
        buffer = self.createBuffer('filter-base', winx, winy, texgroup)
        if buffer == None:
            return None

        cm = CardMaker('filter-base-quad')
        cm.setFrameFullscreenQuad()
        quad = NodePath(cm.generate())
        quad.setDepthTest(0)
        quad.setDepthWrite(0)
        quad.setTexture(colortex)
        quad.setColor(Vec4(1, 0.5, 0.5, 1))
        cs = NodePath('dummy')
        cs.setState(self.camstate)
        if auxbits:
            cs.setAttrib(AuxBitplaneAttrib.make(auxbits))

        self.camera.node().setInitialState(cs.getState())
        quadcamnode = Camera('filter-quad-cam')
        lens = OrthographicLens()
        lens.setFilmSize(2, 2)
        lens.setFilmOffset(0, 0)
        lens.setNearFar(-1000, 1000)
        quadcamnode.setLens(lens)
        quadcam = quad.attachNewNode(quadcamnode)
        self.region.setCamera(quadcam)
        dr = buffer.getDisplayRegion(0)
        self.setStackedClears(dr, self.rclears, self.wclears)
        if auxtex:
            dr.setClearActive(GraphicsOutput.RTPAuxRgba0, 1)
            dr.setClearValue(GraphicsOutput.RTPAuxRgba0,
                             Vec4(0.5, 0.5, 1.0, 0.0))

        self.region.disableClears()
        if self.isFullscreen():
            self.win.disableClears()

        dr.setCamera(self.camera)
        dr.setActive(1)
        self.buffers.append(buffer)
        self.sizes.append((1, 1, 1))
        return quad
예제 #9
0
class DistributedGardenBox(DistributedLawnDecor.DistributedLawnDecor):
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'DistributedGardenPlot')

    def __init__(self, cr):
        DistributedLawnDecor.DistributedLawnDecor.__init__(self, cr)
        #self.defaultModel = "phase_8/models/props/flower_treasure.bam"

        self.plantPath = NodePath('plantPath')
        self.plantPath.reparentTo(self)
        self.plotScale = 1.0

        self.plantingGuiDoneEvent = "plantingGuiDone"
        self.defaultModel = "phase_5.5/models/estate/planterC"

    def announceGenerate(self):
        #print("box announceGenerate!!!!")
        self.notify.debug('announceGenerate')
        DistributedLawnDecor.DistributedLawnDecor.announceGenerate(self)

    def doModelSetup(self):
        if self.typeIndex == GardenGlobals.BOX_THREE:
            self.defaultModel = "phase_5.5/models/estate/planterA"
        elif self.typeIndex == GardenGlobals.BOX_TWO:
            self.defaultModel = "phase_5.5/models/estate/planterC"
        else:
            self.defaultModel = "phase_5.5/models/estate/planterD"
            self.collSphereOffset = 0.0
            self.collSphereRadius = self.collSphereRadius * 1.41
            self.plotScale = Vec3(1.0, 1.0, 1.0)

    def setupShadow(self):
        #we don't want the shadow
        pass

    def loadModel(self):
        self.rotateNode = self.plantPath.attachNewNode('rotate')
        self.model = None

        self.model = loader.loadModel(self.defaultModel)
        self.model.setScale(self.plotScale)
        self.model.reparentTo(self.rotateNode)
        self.stick2Ground()

        #uncomment line below if we want the toons to walk on top of the planter
        #self.model.find("**/collision").stash()

    def handleEnterPlot(self, entry=None):
        #print("Box entered")
        pass

    def handleExitPlot(self, entry=None):
        DistributedLawnDecor.DistributedLawnDecor.handleExitPlot(self, entry)
        pass

    def setTypeIndex(self, typeIndex):
        #print("box setting type index!!!!")
        self.typeIndex = typeIndex
예제 #10
0
    def renderQuadInto(self,
                       mul=1,
                       div=1,
                       align=1,
                       depthtex=None,
                       colortex=None,
                       auxtex0=None,
                       auxtex1=None):
        """ Creates an offscreen buffer for an intermediate
        computation. Installs a quad into the buffer.  Returns
        the fullscreen quad.  The size of the buffer is initially
        equal to the size of the main window.  The parameters 'mul',
        'div', and 'align' can be used to adjust that size. """

        texgroup = (depthtex, colortex, auxtex0, auxtex1)

        winx, winy = self.getScaledSize(mul, div, align)

        depthbits = bool(depthtex != None)

        buffer = self.createBuffer("filter-stage", winx, winy, texgroup,
                                   depthbits)

        if (buffer == None):
            return None

        cm = CardMaker("filter-stage-quad")
        cm.setFrameFullscreenQuad()
        quad = NodePath(cm.generate())
        quad.setDepthTest(0)
        quad.setDepthWrite(0)
        quad.setColor(Vec4(1, 0.5, 0.5, 1))

        quadcamnode = Camera("filter-quad-cam")
        lens = OrthographicLens()
        lens.setFilmSize(2, 2)
        lens.setFilmOffset(0, 0)
        lens.setNearFar(-1000, 1000)
        quadcamnode.setLens(lens)
        quadcam = quad.attachNewNode(quadcamnode)

        dr = buffer.makeDisplayRegion((0, 1, 0, 1))
        dr.disableClears()
        dr.setCamera(quadcam)
        dr.setActive(True)
        dr.setScissorEnabled(False)

        # This clear stage is important if the buffer is padded, so that
        # any pixels accidentally sampled in the padded region won't
        # be reading from unititialised memory.
        buffer.setClearColor((0, 0, 0, 1))
        buffer.setClearColorActive(True)

        self.buffers.append(buffer)
        self.sizes.append((mul, div, align))

        return quad
예제 #11
0
 def __init__(self, base, render,  node1, node2, nodeMass=1, springConstant = 1, drag=5, actor1=None, actor2=None, lengthFactor =1):
       self._render = render
       self._base = base
       self._base.enableParticles()
       self._node1 = node1
       self._node2 = node2
       if not actor1:
             self._actor1 = ActorNode()
             node1 = NodePath("PhysicsNode1")
             node1.reparentTo(render)
             anp1 = node1.attachNewNode(self._actor1)
             base.physicsMgr.attachPhysicalNode(self._actor1)
             self._actor1.getPhysicsObject().setMass(nodeMass)
             self._node1.reparentTo(anp1)
       else:
             self._actor1 = actor1
       if not actor2:
             node2 = NodePath("PhysicsNode2")
             node2.reparentTo(render)
             self._actor2 = ActorNode()
             anp2 = node2.attachNewNode(self._actor2)
             base.physicsMgr.attachPhysicalNode(self._actor2)
             self._actor2.getPhysicsObject().setMass(nodeMass)
             self._node2.reparentTo(anp2)
       else:
             self._actor2 = actor2
       self._springConstant = float(springConstant)
       self._drag = float(drag)
       self.lastTime = globalClock.getDt()
       if lengthFactor == 1:
             self._zeroDistance = self._node1.getPos() - self._node2.getPos()
       else:
             vec = self._node1.getPos() - self._node2.getPos()
             vec = Vec3(  (vec.x/lengthFactor), (vec.y/lengthFactor), (vec.z/lengthFactor) )
             self._zeroDistance = vec
       self._force1 = None
       self._force2 = None
       self._lastPosNode1 = self._node1.getPos()
       self._lastPosNode2 = self._node2.getPos()
       self._impulse1 = None
       self._impulse2 = None
       self._timeOut = None
예제 #12
0
    def make_lights(light_spec=None, lname=None):
        """ Create one point light and an ambient light."""
        if lname is None:
            lname = 'lights'
        lights = NodePath(lname)

        if light_spec is None:
            # Create point lights
            plight = PointLight('plight1')
            light = lights.attachNewNode(plight)
            plight.setColor((0.1, 0.1, 0.1, 1.0))
            light.setPos((-2, -6, 4))
            light.lookAt(0, 0, 0)

        # Create ambient light
            alight = AmbientLight('alight')
            alight.setColor((1, 1, 1, 1.0))
            lights.attachNewNode(alight)
        else:
            for lspec in light_spec:
                light_type = lspec['type']
                light_name = lspec['name']
                assert light_type in ['AmbientLight', 'PointLight',  'DirectionalLight', 'SpotLight'], light_type
                if light_type == 'AmbientLight':
                    light = AmbientLight(light_name)
                    light.setColor(lspec['color'])
                    lights.attachNewNode(light)
                elif light_type == 'PointLight':
                    light = PointLight(light_name)
                    lights.attachNewNode(light)
                    light.setColor(lspec['color'])
                    light.setPoint(lspec['pos'])
                elif light_type == 'DirectionalLight':
                    light = DirectionalLight(light_name)
                    lights.attachNewNode(light)
                    light.setColor(lspec['color'])
                    light.setPoint(lspec['pos'])
                    light.setDirection(lspec['direction'])
                    

        return lights
예제 #13
0
def setSky(directory, ext=".jpg"):
    """Sets up a skybox. 'directory' is the directory whitch contains 6
    pictures with the names right.ext, left.ext and so on (see template).
    ext is the extension the pictures have (with dot).
    """
    #TODO: accept all supported image file extensions without the need for an
    #      extra argument

    # remove the old sky first when loading a new one
    # TODO: get this working...
    #oldsky = render.find("*sky*")
    #print oldsky
    #for child in render.getChildren():
    #    child.remove()

    sky = NodePath().attachNewNode("sky")
    sides = {
        "right":  ( 1,  0,  0, -90,   0,  0),
        "left":   (-1,  0,  0,  90,   0,  0),
        "top":    ( 0,  0,  1,   0,  90,  0),
        "bottom": ( 0,  0, -1,  180,  -90,  0),
        "front":  ( 0,  1,  0,   0,   0,  0),
        "back":   ( 0, -1,  0, 180,   0,  0)
        }
    for name, poshpr in sides.iteritems():

        c = CardMaker(name)
        c.setFrame(-1, 1, -1, 1)
        card = c.generate()
        cardnode = sky.attachNewNode(card)
        cardnode.setPosHpr(*poshpr)
        tex = loader.loadTexture("skyboxes/" + directory + "/" + name + ext)
        tex.setWrapV(tex.WMClamp)
        tex.setMagfilter(tex.FTNearestMipmapNearest)
        tex.setMinfilter(tex.FTNearestMipmapNearest)
        cardnode.setTexture(tex)

    sky.flattenStrong()
    sky.setScale(10, 10, 10)
    sky.setCompass()
    sky.setBin('background', 0)
    sky.setDepthTest(False)
    sky.setDepthWrite(False)
    sky.setLightOff()
    sky.reparentTo(camera)

    geom = sky.getChild(0).node()
    geom.setName("cube")
예제 #14
0
    def renderQuadInto(self,
                       mul=1,
                       div=1,
                       align=1,
                       depthtex=None,
                       colortex=None,
                       auxtex0=None,
                       auxtex1=None):
        """ Creates an offscreen buffer for an intermediate
        computation. Installs a quad into the buffer.  Returns
        the fullscreen quad.  The size of the buffer is initially
        equal to the size of the main window.  The parameters 'mul',
        'div', and 'align' can be used to adjust that size. """

        texgroup = (depthtex, colortex, auxtex0, auxtex1)

        winx, winy = self.getScaledSize(mul, div, align)

        depthbits = bool(depthtex != None)

        buffer = self.createBuffer("filter-stage", winx, winy, texgroup,
                                   depthbits)

        if (buffer == None):
            return None

        cm = CardMaker("filter-stage-quad")
        cm.setFrameFullscreenQuad()
        quad = NodePath(cm.generate())
        quad.setDepthTest(0)
        quad.setDepthWrite(0)
        quad.setColor(Vec4(1, 0.5, 0.5, 1))

        quadcamnode = Camera("filter-quad-cam")
        lens = OrthographicLens()
        lens.setFilmSize(2, 2)
        lens.setFilmOffset(0, 0)
        lens.setNearFar(-1000, 1000)
        quadcamnode.setLens(lens)
        quadcam = quad.attachNewNode(quadcamnode)

        buffer.getDisplayRegion(0).setCamera(quadcam)
        buffer.getDisplayRegion(0).setActive(1)

        self.buffers.append(buffer)
        self.sizes.append((mul, div, align))

        return quad
예제 #15
0
class DistributedGardenBox(DistributedLawnDecor.DistributedLawnDecor):
    __module__ = __name__
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'DistributedGardenPlot')

    def __init__(self, cr):
        DistributedLawnDecor.DistributedLawnDecor.__init__(self, cr)
        self.plantPath = NodePath('plantPath')
        self.plantPath.reparentTo(self)
        self.plotScale = 1.0
        self.plantingGuiDoneEvent = 'plantingGuiDone'
        self.defaultModel = 'phase_5.5/models/estate/planterC'

    def announceGenerate(self):
        self.notify.debug('announceGenerate')
        DistributedLawnDecor.DistributedLawnDecor.announceGenerate(self)

    def doModelSetup(self):
        if self.typeIndex == GardenGlobals.BOX_THREE:
            self.defaultModel = 'phase_5.5/models/estate/planterA'
        elif self.typeIndex == GardenGlobals.BOX_TWO:
            self.defaultModel = 'phase_5.5/models/estate/planterC'
        else:
            self.defaultModel = 'phase_5.5/models/estate/planterD'
            self.collSphereOffset = 0.0
            self.collSphereRadius = self.collSphereRadius * 1.41
            self.plotScale = Vec3(1.0, 1.0, 1.0)

    def setupShadow(self):
        pass

    def loadModel(self):
        self.rotateNode = self.plantPath.attachNewNode('rotate')
        self.model = None
        self.model = loader.loadModel(self.defaultModel)
        self.model.setScale(self.plotScale)
        self.model.reparentTo(self.rotateNode)
        self.stick2Ground()
        return

    def handleEnterPlot(self, entry=None):
        pass

    def handleExitPlot(self, entry=None):
        DistributedLawnDecor.DistributedLawnDecor.handleExitPlot(self, entry)

    def setTypeIndex(self, typeIndex):
        self.typeIndex = typeIndex
예제 #16
0
class Creature(object):
    def __init__(self):
        self.nodepath = NodePath(repr(self))
        node = self.nodepath.attachNewNode(CARD_MAKER.generate())
        node.setTexture(self.texture)
        node.setTwoSided(True)
        node.setTransparency(True)
        self.nodepath.setBillboardPointEye()
        self.pos = None
        self.cur_path = []
        #TODO: how to handle creatures actions?
        self.speed = 4
        self.action = random.randint(0, self.speed)

    def goto(self, pos, asteroid):
        self.cur_path = find_path(self.pos, pos, asteroid)
예제 #17
0
class DistributedGardenBox(DistributedLawnDecor.DistributedLawnDecor):
    __module__ = __name__
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGardenPlot')

    def __init__(self, cr):
        DistributedLawnDecor.DistributedLawnDecor.__init__(self, cr)
        self.plantPath = NodePath('plantPath')
        self.plantPath.reparentTo(self)
        self.plotScale = 1.0
        self.plantingGuiDoneEvent = 'plantingGuiDone'
        self.defaultModel = 'phase_5.5/models/estate/planterC'

    def announceGenerate(self):
        self.notify.debug('announceGenerate')
        DistributedLawnDecor.DistributedLawnDecor.announceGenerate(self)

    def doModelSetup(self):
        if self.typeIndex == GardenGlobals.BOX_THREE:
            self.defaultModel = 'phase_5.5/models/estate/planterA'
        elif self.typeIndex == GardenGlobals.BOX_TWO:
            self.defaultModel = 'phase_5.5/models/estate/planterC'
        else:
            self.defaultModel = 'phase_5.5/models/estate/planterD'
            self.collSphereOffset = 0.0
            self.collSphereRadius = self.collSphereRadius * 1.41
            self.plotScale = Vec3(1.0, 1.0, 1.0)

    def setupShadow(self):
        pass

    def loadModel(self):
        self.rotateNode = self.plantPath.attachNewNode('rotate')
        self.model = None
        self.model = loader.loadModel(self.defaultModel)
        self.model.setScale(self.plotScale)
        self.model.reparentTo(self.rotateNode)
        self.stick2Ground()
        return

    def handleEnterPlot(self, entry = None):
        pass

    def handleExitPlot(self, entry = None):
        DistributedLawnDecor.DistributedLawnDecor.handleExitPlot(self, entry)

    def setTypeIndex(self, typeIndex):
        self.typeIndex = typeIndex
예제 #18
0
 def redraw(self):
     if not self.dirty:
         return  # nothing has changed, no need to redraw
     container = NodePath(PandaNode(self.name + "container"))
     for i in range(TILE_GRP_SIZE):
         for j in range(TILE_GRP_SIZE):
             cur = self.textures[i][j]
             if cur:
                 node = container.attachNewNode(CARD_MAKER.generate())
                 node.setTexture(cur)
                 node.setTwoSided(True)
                 node.setPos(i * TILE_SIZE, 0, j * TILE_SIZE)
     container.flattenStrong()
     for child in self.nodepath.getChildren():
         child.removeNode()
     container.reparentTo(self.nodepath)
     self.dirty = False
    def stick2Ground(self, taskfooler=0):
        if self.isEmpty():
            return Task.done

        testPath = NodePath('testPath')
        testPath.reparentTo(render)
        cRay = CollisionRay(0.0, 0.0, 40000.0, 0.0, 0.0, -1.0)
        cRayNode = CollisionNode(self.uniqueName('estate-FloorRay'))
        cRayNode.addSolid(cRay)
        cRayNode.setFromCollideMask(OTPGlobals.FloorBitmask)
        cRayNode.setIntoCollideMask(BitMask32.allOff())
        cRayNodePath = testPath.attachNewNode(cRayNode)
        queue = CollisionHandlerQueue()
        picker = CollisionTraverser()
        picker.addCollider(cRayNodePath, queue)
        if self.movieNode:
            testPath.setPos(self.movieNode.getX(render),
                            self.movieNode.getY(render), 0)
            picker.traverse(render)
            if queue.getNumEntries() > 0:
                queue.sortEntries()
                for index in range(queue.getNumEntries()):
                    entry = queue.getEntry(index)
                    if recurseParent(entry.getIntoNode(), 'terrain_DNARoot'):
                        self.movieNode.setZ(entry.getSurfacePoint(self)[2])
                        continue

        testPath.setPos(self.getX(), self.getY(), 0)
        picker.traverse(render)
        if queue.getNumEntries() > 0:
            queue.sortEntries()
            for index in range(queue.getNumEntries()):
                entry = queue.getEntry(index)
                if recurseParent(entry.getIntoNode(), 'terrain_DNARoot'):
                    self.setZ(
                        entry.getSurfacePoint(render)[2] + self.stickUp +
                        0.10000000000000001)
                    self.stickParts()
                    return Task.done
                    continue

        taskMgr.doMethodLater(1.0, self.stick2Ground,
                              uniqueName('groundsticker'))
        return Task.done
예제 #20
0
 def createRainDrop(self, x=0, y=0, doubleDrop=False, tripleDrop=False):
     # Set up line geometry for rain.
     id = str(uuid.uuid4())
     dummy = NodePath('dummy' + id)
     lineSegs = LineSegs('line' + id)
     if self.tripleDrop:
         lineSegs.setThickness(3.0)
     elif self.doubleDrop:
         lineSegs.setThickness(2.0)
     else:
         lineSegs.setThickness(1.0)
     lineSegs.moveTo(0, 0, 0)
     lineSegs.drawTo(0, 0, self.deltaZ * .1)
     lineGeomNode = lineSegs.create()
     # True: gray; False: white and red.
     if True:
         lineSegs.setVertexColor(0, Vec4(1, 1, 1, .4))
         lineSegs.setVertexColor(1, Vec4(.3, .3, .3, 0))
         pass
     else:
         lineSegs.setVertexColor(0, Vec4(1, 1, 1, .4))
         lineSegs.setVertexColor(1, Vec4(1, 0, 0, 1))
     linePath = dummy.attachNewNode(lineGeomNode)
     linePath.setTransparency(True)
     linePath.reparentTo(render)
     # Add collision node with 'FROM' tag = 'rain'
     pickerNode = CollisionNode('linecnode' + id)
     pickerNode.setTag('FROM', 'rain')
     rayCollider = linePath.attachNewNode(pickerNode)
     # A small collision sphere is attached to the bottom of each rain drop.
     rayCollider.node().addSolid(CollisionSphere(0, 0, 0, .25))
     #base.cTrav.addCollider(rayCollider, collisionHandler)
     # Sequence rain
     Sequence(
         LerpPosInterval(linePath,
                         self.dropDuration,
                         Point3(x, y, self.pt1.z),
                         Point3(x, y, self.pt2.z),
                         blendType='easeIn',
                         fluid=1),
         Parallel(Func(dummy.removeNode),
                  Func(linePath.removeNode))).start()
예제 #21
0
    def renderQuadInto(self, mul=1, div=1, align=1, depthtex=None, colortex=None, auxtex0=None, auxtex1=None):

        """ Creates an offscreen buffer for an intermediate
        computation. Installs a quad into the buffer.  Returns
        the fullscreen quad.  The size of the buffer is initially
        equal to the size of the main window.  The parameters 'mul',
        'div', and 'align' can be used to adjust that size. """

        texgroup = (depthtex, colortex, auxtex0, auxtex1)

        winx, winy = self.getScaledSize(mul, div, align)
        
        depthbits = bool(depthtex != None)
        
        buffer = self.createBuffer("filter-stage", winx, winy, texgroup, depthbits)

        if (buffer == None):
            return None

        cm = CardMaker("filter-stage-quad")
        cm.setFrameFullscreenQuad()
        quad = NodePath(cm.generate())
        quad.setDepthTest(0)
        quad.setDepthWrite(0)
        quad.setColor(Vec4(1,0.5,0.5,1))

        quadcamnode = Camera("filter-quad-cam")
        lens = OrthographicLens()
        lens.setFilmSize(2, 2)
        lens.setFilmOffset(0, 0)
        lens.setNearFar(-1000, 1000)
        quadcamnode.setLens(lens)
        quadcam = quad.attachNewNode(quadcamnode)
        
        buffer.getDisplayRegion(0).setCamera(quadcam)
        buffer.getDisplayRegion(0).setActive(1)

        self.buffers.append(buffer)
        self.sizes.append((mul, div, align))
        
        return quad
	def getGameOverNode(self):
		gameOverNode=NodePath("GameOver")

		letterGeometry=LetterGeometry.getCardGeometryByPhrase('game over')

		for letter in letterGeometry:
			letterCm=CardMaker('card')
			letterCm.setFrame(letter['left'],letter['right'],letter['top'],letter['bottom'])
			letterNode=gameOverNode.attachNewNode(letterCm.generate())
			self.letterNodes.append(letterNode)
			letterNode.setTwoSided(True)
			letterNode.setTransparency(TransparencyAttrib.MAlpha)
			letterNode.setBin('unsorted',50)
			letterNode.setDepthTest(False)
			letterNode.setDepthWrite(False)
			tex=loader.loadTexture('textures/letter-'+letter['letter']+'.png')
			tex.setWrapU(Texture.WMClamp)
			tex.setWrapV(Texture.WMClamp)
			letterNode.setTexture(tex)
			letterNode.setPos(letter['originx'],letter['originy'],0)
	
		return gameOverNode
    def generate(self):
        DistCogdoGameAI.generate(self)
        mazeFactory = self.createMazeFactory(self.createRandomNumGen())
        waterCoolerList = []
        mazeModel = mazeFactory._loadAndBuildMazeModel()
        for waterCooler in mazeModel.findAllMatches('**/*waterCooler'):
            waterCoolerList.append(
                (waterCooler.getPos(mazeModel), waterCooler.getHpr(mazeModel)))

        waterCoolerList.sort()
        baseNp = NodePath('base')
        rotNp = baseNp.attachNewNode('rot')
        childNp = rotNp.attachNewNode('child')
        childNp.setPos(*Globals.WaterCoolerTriggerOffset)
        self._waterCoolerPosList = []
        for (pos, hpr) in waterCoolerList:
            rotNp.setHpr(hpr)
            offset = childNp.getPos(baseNp)
            self._waterCoolerPosList.append(pos + offset)

        self._speedMonitor = SpeedMonitor('cogdoMazeGame-%s' % self.doId)
        self._toonId2speedToken = {}
예제 #24
0
    def stick2Ground(self, taskfooler = 0):
        if self.isEmpty():
            return Task.done
        testPath = NodePath('testPath')
        testPath.reparentTo(render)
        cRay = CollisionRay(0.0, 0.0, 40000.0, 0.0, 0.0, -1.0)
        cRayNode = CollisionNode(self.uniqueName('estate-FloorRay'))
        cRayNode.addSolid(cRay)
        cRayNode.setFromCollideMask(OTPGlobals.FloorBitmask)
        cRayNode.setIntoCollideMask(BitMask32.allOff())
        cRayNodePath = testPath.attachNewNode(cRayNode)
        queue = CollisionHandlerQueue()
        picker = CollisionTraverser()
        picker.addCollider(cRayNodePath, queue)
        if self.movieNode:
            testPath.setPos(self.movieNode.getX(render), self.movieNode.getY(render), 0)
            picker.traverse(render)
            if queue.getNumEntries() > 0:
                queue.sortEntries()
                for index in xrange(queue.getNumEntries()):
                    entry = queue.getEntry(index)
                    if recurseParent(entry.getIntoNode(), 'terrain_DNARoot'):
                        self.movieNode.setZ(entry.getSurfacePoint(self)[2])

        testPath.setPos(self.getX(), self.getY(), 0)
        picker.traverse(render)
        if queue.getNumEntries() > 0:
            queue.sortEntries()
            for index in xrange(queue.getNumEntries()):
                entry = queue.getEntry(index)
                if recurseParent(entry.getIntoNode(), 'terrain_DNARoot'):
                    self.setZ(entry.getSurfacePoint(render)[2] + self.stickUp + 0.1)
                    self.stickParts()
                    return Task.done

        taskMgr.doMethodLater(1.0, self.stick2Ground, uniqueName('groundsticker'))
        return Task.done
예제 #25
0
 def createRainDrop(self, x=0, y=0, doubleDrop=False, tripleDrop=False):
     # Set up line geometry for rain.
     id = str(uuid.uuid4())
     dummy = NodePath('dummy'+id)
     lineSegs = LineSegs('line'+id)
     if self.tripleDrop:
         lineSegs.setThickness(3.0)
     elif self.doubleDrop:
         lineSegs.setThickness(2.0)
     else:
         lineSegs.setThickness(1.0)
     lineSegs.moveTo(0, 0, 0)
     lineSegs.drawTo(0, 0, self.deltaZ*.1)
     lineGeomNode = lineSegs.create()
     # True: gray; False: white and red.
     if True:
         lineSegs.setVertexColor(0, Vec4(1, 1, 1, .4))
         lineSegs.setVertexColor(1, Vec4(.3, .3, .3, 0))
         pass
     else:
         lineSegs.setVertexColor(0, Vec4(1, 1, 1, .4))
         lineSegs.setVertexColor(1, Vec4(1, 0, 0, 1))
     linePath = dummy.attachNewNode(lineGeomNode)
     linePath.setTransparency(True)
     linePath.reparentTo(render)
     # Add collision node with 'FROM' tag = 'rain'
     pickerNode = CollisionNode('linecnode'+id)
     pickerNode.setTag('FROM', 'rain')
     rayCollider = linePath.attachNewNode(pickerNode)
     # A small collision sphere is attached to the bottom of each rain drop.
     rayCollider.node().addSolid(CollisionSphere(0, 0, 0, .25))
     #base.cTrav.addCollider(rayCollider, collisionHandler)
     # Sequence rain
     Sequence(
         LerpPosInterval(linePath, self.dropDuration, Point3(x, y, self.pt1.z), Point3(x, y, self.pt2.z), blendType='easeIn', fluid=1),
         Parallel(Func(dummy.removeNode), Func(linePath.removeNode))
     ).start()
예제 #26
0
    def getGameOverNode(self):
        gameOverNode = NodePath("GameOver")

        letterGeometry = LetterGeometry.getCardGeometryByPhrase('game over')

        for letter in letterGeometry:
            letterCm = CardMaker('card')
            letterCm.setFrame(letter['left'], letter['right'], letter['top'],
                              letter['bottom'])
            letterNode = gameOverNode.attachNewNode(letterCm.generate())
            self.letterNodes.append(letterNode)
            letterNode.setTwoSided(True)
            letterNode.setTransparency(TransparencyAttrib.MAlpha)
            letterNode.setBin('unsorted', 50)
            letterNode.setDepthTest(False)
            letterNode.setDepthWrite(False)
            tex = loader.loadTexture('textures/letter-' + letter['letter'] +
                                     '.png')
            tex.setWrapU(Texture.WMClamp)
            tex.setWrapV(Texture.WMClamp)
            letterNode.setTexture(tex)
            letterNode.setPos(letter['originx'], letter['originy'], 0)

        return gameOverNode
예제 #27
0
class PartyCog(FSM):
    notify = directNotify.newCategory("PartyCog")

    HpTextGenerator = TextNode("HpTextGenerator")
    hpText = None
    height = 7

    def __init__(self,
                 parentNode,
                 id,
                 bounceSpeed=3,
                 bounceHeight=1,
                 rotateSpeed=1,
                 heightShift=1,
                 xMoveSpeed=0,
                 xMoveDistance=0,
                 bounceOffset=0):
        self.id = id

        FSM.__init__(self, "PartyCogFSM-%d" % self.id)

        self.showFacingStatus = False
        self.xMoveSpeed = xMoveSpeed
        self.xMoveDistance = xMoveDistance
        self.heightShift = heightShift
        self.bounceSpeed = bounceSpeed
        self.bounceHeight = bounceHeight
        self.rotateSpeed = rotateSpeed
        self.parentNode = parentNode
        self.bounceOffset = bounceOffset
        self.hitInterval = None
        self.kaboomTrack = None
        self.resetRollIval = None
        self.netTimeSentToStartByHit = 0

        self.load()
        self.request("Down")

    def load(self):
        self.root = NodePath("PartyCog-%d" % self.id)
        self.root.reparentTo(self.parentNode)

        path = "phase_13/models/parties/cogPinata_"
        self.actor = Actor(
            path + "actor", {
                "idle": path + "idle_anim",
                "down": path + "down_anim",
                "up": path + "up_anim",
                "bodyHitBack": path + "bodyHitBack_anim",
                "bodyHitFront": path + "bodyHitFront_anim",
                "headHitBack": path + "headHitBack_anim",
                "headHitFront": path + "headHitFront_anim",
            })
        self.actor.reparentTo(self.root)

        self.temp_transform = Mat4()
        self.head_locator = self.actor.attachNewNode("temphead")

        self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75)
        self.bodyColl.setTangible(1)
        self.bodyCollNode = CollisionNode("PartyCog-%d-Body-Collision" %
                                          self.id)
        self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.bodyCollNode.addSolid(self.bodyColl)
        self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode)

        self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5)
        self.headColl.setTangible(1)
        self.headCollNode = CollisionNode("PartyCog-%d-Head-Collision" %
                                          self.id)
        self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.headCollNode.addSolid(self.headColl)
        self.headCollNodePath = self.root.attachNewNode(self.headCollNode)

        # Cog's Left Arm
        self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0)
        self.arm1Coll.setTangible(1)
        self.arm1CollNode = CollisionNode("PartyCog-%d-Arm1-Collision" %
                                          self.id)
        self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm1CollNode.addSolid(self.arm1Coll)
        self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode)

        # Cog's Right Arm
        self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0)
        self.arm2Coll.setTangible(1)
        self.arm2CollNode = CollisionNode("PartyCog-%d-Arm2-Collision" %
                                          self.id)
        self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask)
        self.arm2CollNode.addSolid(self.arm2Coll)
        self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode)

        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splatType = globalPropPool.getPropType(splatName)

        self.pieHitSound = globalBattleSoundCache.getSound(
            'AA_wholepie_only.mp3')
        self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.mp3')

        self.hole = loader.loadModel("phase_13/models/parties/cogPinataHole")
        self.hole.setTransparency(True)
        self.hole.setP(-90.0)
        self.hole.setScale(3)
        self.hole.setBin("ground", 3)
        self.hole.reparentTo(self.parentNode)

    def unload(self):
        self.request("Off")
        self.clearHitInterval()

        if self.hole is not None:
            self.hole.removeNode()
            self.hole = None

        if self.actor is not None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None

        if self.root is not None:
            self.root.removeNode()
            self.root = None

        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.kaboomTrack = None

        if self.resetRollIval is not None and self.resetRollIval.isPlaying():
            self.resetRollIval.finish()
        self.resetRollIval = None

        if self.hitInterval is not None and self.hitInterval.isPlaying():
            self.hitInterval.finish()
        self.hitInterval = None

        del self.upSound
        del self.pieHitSound

#===============================================================================
# FSM States
#===============================================================================

    def enterStatic(self):
        pass

    def exitStatic(self):
        pass

    def enterActive(self, startTime):
        self.root.setR(0.0)

        updateTask = Task.Task(self.updateTask)
        updateTask.startTime = startTime

        taskMgr.add(updateTask, "PartyCog.update-%d" % self.id)

    def exitActive(self):
        taskMgr.remove("PartyCog.update-%d" % self.id)
        taskMgr.remove("PartyCog.bounceTask-%d" % self.id)

        self.clearHitInterval()
        self.resetRollIval = self.root.hprInterval(0.5,
                                                   Point3(
                                                       self.root.getH(), 0.0,
                                                       0.0),
                                                   blendType="easeInOut")
        self.resetRollIval.start()

        self.actor.stop()

    def enterDown(self):
        if self.oldState == "Off":
            downAnimControl = self.actor.getAnimControl("down")
            self.actor.pose("down", downAnimControl.getNumFrames() - 1)
            return

        self.clearHitInterval()
        startScale = self.hole.getScale()
        endScale = Point3(5, 5, 5)
        self.hitInterval = Sequence(
            LerpFunc(self.setAlongSpline,
                     duration=1.0,
                     fromData=self.currentT,
                     toData=0.0),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=endScale,
                              startScale=startScale,
                              blendType="easeIn"),
            Parallel(
                SoundInterval(self.upSound,
                              volume=0.6,
                              node=self.actor,
                              cutOff=PartyGlobals.PARTY_COG_CUTOFF),
                ActorInterval(self.actor, "down", loop=0),
            ),
            LerpScaleInterval(self.hole,
                              duration=0.175,
                              scale=Point3(3, 3, 3),
                              startScale=endScale,
                              blendType="easeOut"),
        )
        self.hitInterval.start()

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

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

#------------------------------------------------------------------------------

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

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

        self.root.setR(angle)

        #        if self.id == 0:
        #            print angle

        return task.cont

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

    def updateTask(self, task):
        self.rockBackAndForth(task)

        if self.targetDistance > self.currentT:
            self.currentT += min(0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)
        elif self.targetDistance < self.currentT:
            self.currentT += max(-0.01, self.targetDistance - self.currentT)
            self.setAlongSpline(self.currentT)

        if self.currentT < 0.0:
            self.targetFacing = -90.0
        elif self.currentT > 0.0:
            self.targetFacing = 90.0
        else:
            self.targetFacing = 0.0

        if self.targetFacing > self.currentFacing:
            self.currentFacing += min(10,
                                      self.targetFacing - self.currentFacing)
        elif self.targetFacing < self.currentFacing:
            self.currentFacing += max(-10,
                                      self.targetFacing - self.currentFacing)

        self.root.setH(self.currentFacing)

        return task.cont

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

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

    def bounce(self, task):
        #self.root.setH(self.root.getH() - self.rotateSpeed)
        self.root.setZ((math.sin((self.bounceOffset + task.time) *
                                 self.bounceSpeed) * self.bounceHeight) +
                       self.heightShift)

        return task.cont

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

    def respondToPieHit(self, timestamp, position, hot=False, direction=1.0):
        """The toon hit us, react appropriately."""
        assert (self.notify.debugStateCall(self))

        if self.netTimeSentToStartByHit < timestamp:
            self.__showSplat(position, direction, hot)

            if self.netTimeSentToStartByHit < timestamp:
                self.netTimeSentToStartByHit = timestamp
        else:
            #self.notify.debug('localStamp = %s, lastLocalTimeStampFromAI=%s, ignoring respondToPieHit' % (localStamp, self.lastLocalTimeStampFromAI))
            self.notify.debug(
                'respondToPieHit self.netTimeSentToStartByHit = %s' %
                self.netTimeSentToStartByHit)

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

    def __showSplat(self, position, direction, hot=False):
        """Show the splat graphic and sound."""
        if self.kaboomTrack is not None and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()

        self.clearHitInterval()
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()

        self.splat.reparentTo(render)
        self.splat.setPos(self.root, position)
        self.splat.setAlphaScale(1.0)

        if not direction == 1.0:
            #self.splat.setColorScale(Vec4(0.0, 0.0, 50.0, 1.0))
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0])
            if self.currentFacing > 0.0:
                facing = "HitFront"
            else:
                facing = "HitBack"
        else:
            self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1])
            #self.splat.setColorScale(Vec4(1.0, 0.6, 0.08, 1.0))
            if self.currentFacing > 0.0:
                facing = "HitBack"
            else:
                facing = "HitFront"

        if hot:
            targetscale = 0.75
            part = "head"
        else:
            targetscale = 0.5
            part = "body"

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

        self.hitInterval = Sequence(
            ActorInterval(self.actor, part + facing, loop=0),
            Func(self.actor.loop, "idle"),
        )
        self.hitInterval.start()

        self.kaboomTrack = Parallel(
            SoundInterval(self.pieHitSound,
                          volume=1.0,
                          node=self.actor,
                          cutOff=PartyGlobals.PARTY_COG_CUTOFF),
            Sequence(
                Func(self.splat.showThrough),
                Parallel(
                    Sequence(
                        LerpScaleInterval(self.splat,
                                          duration=0.175,
                                          scale=targetscale,
                                          startScale=Point3(0.1, 0.1, 0.1),
                                          blendType="easeOut"),
                        Wait(0.175),
                    ),
                    Sequence(
                        Wait(0.1),
                        LerpFunc(
                            setSplatAlpha,
                            duration=1.0,  #0.4,
                            fromData=1.0,
                            toData=0.0,
                            blendType="easeOut"))),
                Func(self.splat.cleanup),
                Func(self.splat.removeNode),
            ))
        self.kaboomTrack.start()

    def showHitScore(self, number, scale=1):
        """
        Shows the hit score.
        Borrowed from otp.avatar.DistributedAvatar.showHpText
        """
        if number <= 0:
            return

        # Get rid of the number if it is already there.
        if self.hpText:
            self.hideHitScore()

        # Set the font
        self.HpTextGenerator.setFont(ToontownGlobals.getSignFont())

        # Show both negative and positive signs
        if number < 0:
            self.HpTextGenerator.setText(str(number))
        else:
            self.HpTextGenerator.setText("+" + str(number))

        # No shadow
        self.HpTextGenerator.clearShadow()

        # Center the number
        self.HpTextGenerator.setAlign(TextNode.ACenter)

        # Red, always
        #if number < 0:
        r = 1  #0.9
        g = 1  #0
        b = 0
        a = 1

        self.HpTextGenerator.setTextColor(r, g, b, a)

        self.hpTextNode = self.HpTextGenerator.generate()

        # Put the hpText over the head of the avatar
        self.hpText = render.attachNewNode(self.hpTextNode)
        self.hpText.setScale(scale)
        # Make sure it is a billboard
        self.hpText.setBillboardPointEye()
        # Render it after other things in the scene.
        self.hpText.setBin('fixed', 100)

        # Initial position ... Center of the body... the "tan tien"
        self.hpText.setPos(self.root, 0, 0, self.height / 2)

        # Black magic from the early days of Panda3D, later replaced by a Sequence
        seq = Task.sequence(
            # Fly the number out of the character
            self.hpText.lerpPos(Point3(
                self.root.getX(render), self.root.getY(render),
                self.root.getZ(render) + self.height + 1.0),
                                0.25,
                                blendType='easeOut'),
            Task.pause(0.25),
            # Fade the number
            self.hpText.lerpColor(Vec4(r, g, b, a), Vec4(r, g, b, 0), 0.1),
            # Get rid of the number
            Task.Task(self.__hideHitScoreTask))

        taskMgr.add(seq, "PartyCogHpText" + str(self.id))

    def __hideHitScoreTask(self, task):
        self.hideHitScore()

        return Task.done

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

    def getHeadLocation(self):
        (self.actor.getJoints(jointName="head")[0]).getNetTransform(
            self.temp_transform)
        self.head_locator.setMat(self.temp_transform)
        #print self.head_locator.getZ()

        return self.head_locator.getZ(self.root)
예제 #28
0
avatar = loader.loadModel('smiley')
avatar.reparentTo(avatarNP)
# since our avatar origin is centered in a model sized 2,2,2, we need to shift it 1 unit above the ground and this time we make this happen shifting it off its own root node (avatarNP)
avatar.setPos(0, 0, 1)
avatar.setCollideMask(BitMask32.allOff())
avatarNP.setPos(0, 0, 15)
# we reintroduced in this snippet the renowned smiley collision sphere - we need it as low-poly collision geometry for the wall collision handler to know when the smiley hit a wall.
avatarCollider = avatar.attachNewNode(CollisionNode('smileycnode'))
avatarCollider.node().addSolid(CollisionSphere(0, 0, 0, 1))
# of course we mark it with the wall mask
avatarCollider.node().setFromCollideMask(WALL_MASK)
avatarCollider.node().setIntoCollideMask(BitMask32.allOff())

#** Here we stick and set the ray collider to the avatar - note that we set it well above the avatar position because like this we are sure to always find a floor surface higher than the avatar top - try to change the third value i.e. to 0 and see what happen steering the avatar to get what I mean
raygeometry = CollisionRay(0, 0, 2, 0, 0, -1)
avatarRay = avatarNP.attachNewNode(CollisionNode('avatarRay'))
avatarRay.node().addSolid(raygeometry)
# this is how we tell the collision system that this ray would collide just with the floor acting as a FROM collider.
avatarRay.node().setFromCollideMask(FLOOR_MASK)
# we then exclude the ray from acting as an INTO collider
avatarRay.node().setIntoCollideMask(BitMask32.allOff())

#** This is the terrain map - the egg model loaded contains also the collider geometry for the terrain and for the walls as childs
terrain = loader.loadModel("scene1")
terrain.reparentTo(render)
terrain.setCollideMask(BitMask32.allOff())
terrain.setScale(10)
# here how we tell the collision system that the terrain collider geometry is allowed to collide with the avatar ray as INTO collider...
floorcollider = terrain.find("**/floor_collide")
floorcollider.node().setIntoCollideMask(FLOOR_MASK)
#...and the same goes for the walls
예제 #29
0
class Sprite2d:
    class Cell:
        def __init__(self, col, row):
            self.col = col
            self.row = row

        def __str__(self):
            return "Cell - Col %d, Row %d" % (self.col, self.row)

    class Animation:
        def __init__(self, cells, fps):
            self.cells = cells
            self.fps = fps
            self.playhead = 0

    ALIGN_CENTER = "Center"
    ALIGN_LEFT = "Left"
    ALIGN_RIGHT = "Right"
    ALIGN_BOTTOM = "Bottom"
    ALIGN_TOP = "Top"

    TRANS_ALPHA = TransparencyAttrib.MAlpha
    TRANS_DUAL = TransparencyAttrib.MDual
    # One pixel is divided by this much. If you load a 100x50 image with PIXEL_SCALE of 10.0
    # you get a card that is 1 unit wide, 0.5 units high
    PIXEL_SCALE = 20.0

    def __init__(self, image_path, rowPerFace, name=None,\
         rows=1, cols=1, scale=1.0,\
         twoSided=False, alpha=TRANS_ALPHA,\
         repeatX=1, repeatY=1,\
         anchorX=ALIGN_CENTER, anchorY=ALIGN_BOTTOM):
        """
		Create a card textured with an image. The card is sized so that the ratio between the
		card and image is the same.
		"""

        global SpriteId
        self.spriteNum = str(SpriteId)
        SpriteId += 1

        scale *= self.PIXEL_SCALE

        self.animations = {}

        self.scale = scale
        self.repeatX = repeatX
        self.repeatY = repeatY
        self.flip = {'x': False, 'y': False}
        self.rows = rows
        self.cols = cols

        self.currentFrame = 0
        self.currentAnim = None
        self.loopAnim = False
        self.frameInterrupt = True

        # Create the NodePath
        if name:
            self.node = NodePath("Sprite2d:%s" % name)
        else:
            self.node = NodePath("Sprite2d:%s" % image_path)

        # Set the attribute for transparency/twosided
        self.node.node().setAttrib(TransparencyAttrib.make(alpha))
        if twoSided:
            self.node.setTwoSided(True)

        # Make a filepath
        self.imgFile = Filename(image_path)
        if self.imgFile.empty():
            raise IOError, "File not found"

        # Instead of loading it outright, check with the PNMImageHeader if we can open
        # the file.
        imgHead = PNMImageHeader()
        if not imgHead.readHeader(self.imgFile):
            raise IOError, "PNMImageHeader could not read file. Try using absolute filepaths"

        # Load the image with a PNMImage
        image = PNMImage()
        image.read(self.imgFile)

        self.sizeX = image.getXSize()
        self.sizeY = image.getYSize()

        # We need to find the power of two size for the another PNMImage
        # so that the texture thats loaded on the geometry won't have artifacts
        textureSizeX = self.nextsize(self.sizeX)
        textureSizeY = self.nextsize(self.sizeY)

        # The actual size of the texture in memory
        self.realSizeX = textureSizeX
        self.realSizeY = textureSizeY

        self.paddedImg = PNMImage(textureSizeX, textureSizeY)
        if image.hasAlpha():
            self.paddedImg.alphaFill(0)
        # Copy the source image to the image we're actually using
        self.paddedImg.blendSubImage(image, 0, 0)
        # We're done with source image, clear it
        image.clear()

        # The pixel sizes for each cell
        self.colSize = self.sizeX / self.cols
        self.rowSize = self.sizeY / self.rows

        # How much padding the texture has
        self.paddingX = textureSizeX - self.sizeX
        self.paddingY = textureSizeY - self.sizeY

        # Set UV padding
        self.uPad = float(self.paddingX) / textureSizeX
        self.vPad = float(self.paddingY) / textureSizeY

        # The UV dimensions for each cell
        self.uSize = (1.0 - self.uPad) / self.cols
        self.vSize = (1.0 - self.vPad) / self.rows

        self.cards = []
        self.rowPerFace = rowPerFace
        for i in range(len(rowPerFace)):
            card = CardMaker("Sprite2d-Geom")

            # The positions to create the card at
            if anchorX == self.ALIGN_LEFT:
                posLeft = 0
                posRight = (self.colSize / scale) * repeatX
            elif anchorX == self.ALIGN_CENTER:
                posLeft = -(self.colSize / 2.0 / scale) * repeatX
                posRight = (self.colSize / 2.0 / scale) * repeatX
            elif anchorX == self.ALIGN_RIGHT:
                posLeft = -(self.colSize / scale) * repeatX
                posRight = 0

            if anchorY == self.ALIGN_BOTTOM:
                posTop = 0
                posBottom = (self.rowSize / scale) * repeatY
            elif anchorY == self.ALIGN_CENTER:
                posTop = -(self.rowSize / 2.0 / scale) * repeatY
                posBottom = (self.rowSize / 2.0 / scale) * repeatY
            elif anchorY == self.ALIGN_TOP:
                posTop = -(self.rowSize / scale) * repeatY
                posBottom = 0

            card.setFrame(posLeft, posRight, posTop, posBottom)
            card.setHasUvs(True)
            self.cards.append(self.node.attachNewNode(card.generate()))
            self.cards[-1].setH(i * 360 / len(rowPerFace))

        # Since the texture is padded, we need to set up offsets and scales to make
        # the texture fit the whole card
        self.offsetX = (float(self.colSize) / textureSizeX)
        self.offsetY = (float(self.rowSize) / textureSizeY)

        # self.node.setTexScale(TextureStage.getDefault(), self.offsetX * repeatX, self.offsetY * repeatY)
        # self.node.setTexOffset(TextureStage.getDefault(), 0, 1-self.offsetY)

        self.texture = Texture()

        self.texture.setXSize(textureSizeX)
        self.texture.setYSize(textureSizeY)
        self.texture.setZSize(1)

        # Load the padded PNMImage to the texture
        self.texture.load(self.paddedImg)

        self.texture.setMagfilter(Texture.FTNearest)
        self.texture.setMinfilter(Texture.FTNearest)

        #Set up texture clamps according to repeats
        if repeatX > 1:
            self.texture.setWrapU(Texture.WMRepeat)
        else:
            self.texture.setWrapU(Texture.WMClamp)
        if repeatY > 1:
            self.texture.setWrapV(Texture.WMRepeat)
        else:
            self.texture.setWrapV(Texture.WMClamp)

        self.node.setTexture(self.texture)
        self.setFrame(0)

    def nextsize(self, num):
        """ Finds the next power of two size for the given integer. """
        p2x = max(1, log(num, 2))
        notP2X = modf(p2x)[0] > 0
        return 2**int(notP2X + p2x)

    def setFrame(self, frame=0):
        """ Sets the current sprite to the given frame """
        self.frameInterrupt = True  # A flag to tell the animation task to shut it up ur face
        self.currentFrame = frame
        self.flipTexture()

    def playAnim(self, animName, loop=False):
        """ Sets the sprite to animate the given named animation. Booleon to loop animation"""
        if not taskMgr.hasTaskNamed("Animate sprite" + self.spriteNum):
            if hasattr(self, "task"):
                taskMgr.remove("Animate sprite" + self.spriteNum)
                del self.task
            self.frameInterrupt = False  # Clear any previous interrupt flags
            self.loopAnim = loop
            self.currentAnim = self.animations[animName]
            self.currentAnim.playhead = 0
            self.task = taskMgr.doMethodLater(
                1.0 / self.currentAnim.fps, self.animPlayer,
                "Animate sprite" + self.spriteNum)

    def createAnim(self, animName, frameCols, fps=12):
        """ Create a named animation. Takes the animation name and a tuple of frame numbers """
        self.animations[animName] = Sprite2d.Animation(frameCols, fps)
        return self.animations[animName]

    def flipX(self, val=None):
        """ Flip the sprite on X. If no value given, it will invert the current flipping."""
        if val:
            self.flip['x'] = val
        else:
            if self.flip['x']:
                self.flip['x'] = False
            else:
                self.flip['x'] = True
        self.flipTexture()
        return self.flip['x']

    def flipY(self, val=None):
        """ See flipX """
        if val:
            self.flip['y'] = val
        else:
            if self.flip['y']:
                self.flip['y'] = False
            else:
                self.flip['y'] = True
        self.flipTexture()
        return self.flip['y']

    def updateCameraAngle(self, cameraNode):
        baseH = cameraNode.getH(render) - self.node.getH(render)
        degreesBetweenCards = 360 / len(self.cards)
        bestCard = int(
            ((baseH) + degreesBetweenCards / 2) % 360 / degreesBetweenCards)
        #print baseH, bestCard
        for i in range(len(self.cards)):
            if i == bestCard:
                self.cards[i].show()
            else:
                self.cards[i].hide()

    def flipTexture(self):
        """ Sets the texture coordinates of the texture to the current frame"""
        for i in range(len(self.cards)):
            currentRow = self.rowPerFace[i]

            sU = self.offsetX * self.repeatX
            sV = self.offsetY * self.repeatY
            oU = 0 + self.currentFrame * self.uSize
            #oU = 0 + self.frames[self.currentFrame].col * self.uSize
            #oV = 1 - self.frames[self.currentFrame].row * self.vSize - self.offsetY
            oV = 1 - currentRow * self.vSize - self.offsetY
            if self.flip['x'] ^ i == 1:  ##hack to fix side view
                #print "flipping, i = ",i
                sU *= -1
                #oU = self.uSize + self.frames[self.currentFrame].col * self.uSize
                oU = self.uSize + self.currentFrame * self.uSize
            if self.flip['y']:
                sV *= -1
                #oV = 1 - self.frames[self.currentFrame].row * self.vSize
                oV = 1 - currentRow * self.vSize
            self.cards[i].setTexScale(TextureStage.getDefault(), sU, sV)
            self.cards[i].setTexOffset(TextureStage.getDefault(), oU, oV)

    def clear(self):
        """ Free up the texture memory being used """
        self.texture.clear()
        self.paddedImg.clear()
        self.node.removeNode()

    def animPlayer(self, task):
        if self.frameInterrupt:
            return task.done
        #print "Playing",self.currentAnim.cells[self.currentAnim.playhead]
        self.currentFrame = self.currentAnim.cells[self.currentAnim.playhead]
        self.flipTexture()
        if self.currentAnim.playhead + 1 < len(self.currentAnim.cells):
            self.currentAnim.playhead += 1
            return task.again
        if self.loopAnim:
            self.currentAnim.playhead = 0
            return task.again
class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'DistributedGardenPlot')
    deferFor = 2

    def __init__(self, cr):
        DistributedLawnDecor.DistributedLawnDecor.__init__(self, cr)
        self.plantPath = NodePath('plantPath')
        self.plantPath.reparentTo(self)
        self.plotScale = 1.0
        self.plantingGuiDoneEvent = 'plantingGuiDone'
        self.toonStatueSelectionDoneEvent = 'toonStatueSelectionDone'
        self.defaultModel = 'phase_5.5/models/estate/dirt_mound'
        self.colorScaler = Vec4(1, 1, 1, 1)
        self.plantingGui = None
        return

    def delete(self):
        if self.plantingGui:
            self.plantingGui.destroy()
            self.plantingGui = None
        DistributedLawnDecor.DistributedLawnDecor.delete(self)
        return

    def announceGenerate(self):
        self.plotType = GardenGlobals.whatCanBePlanted(self.ownerIndex,
                                                       self.plot)
        self.stickUp = 0.0
        if self.getOwnerId() != localAvatar.doId:
            self.defaultModel = None
        elif self.plotType == GardenGlobals.FLOWER_TYPE:
            self.collSphereRadius = 2.0
            self.collSphereOffset = 0.0
            self.plotScale = 0.6
            self.stickUp = 1.1
        elif self.plotType == GardenGlobals.GAG_TREE_TYPE:
            self.collSphereRadius = 3.0
            self.plotScale = 1.5
            self.colorScaler = Vec4(1.0, 1.0, 1.0, 1)
        elif self.plotType == GardenGlobals.STATUARY_TYPE:
            self.collSphereRadius = 3.0
            self.plotScale = 0.075
            self.stickUp = -0.0
            self.defaultModel = 'phase_5.5/models/estate/garden_slab'
        else:
            self.collSphereOffset = 0.0
        self.notify.debug('announceGenerate')
        DistributedLawnDecor.DistributedLawnDecor.announceGenerate(self)
        return

    def loadModel(self):
        self.rotateNode = self.plantPath.attachNewNode('rotate')
        self.model = None
        if self.defaultModel:
            self.model = loader.loadModel(self.defaultModel)
            if type(self.plotScale) == types.TupleType:
                self.model.setScale(*self.plotScale)
            else:
                self.model.setScale(self.plotScale)
            self.model.reparentTo(self.rotateNode)
            self.model.setColorScale(self.colorScaler)
            self.stick2Ground()
        return

    def setupShadow(self):
        pass

    def getShovelCommand(self):
        return self.plantSomething

    def getShovelAction(self):
        return self.getPlantingText()

    def handleEnterPlot(self, entry=None):
        dist = self.getDistance(localAvatar)
        if self.canBePlanted():
            base.localAvatar.addShovelRelatedDoId(self.doId)

    def handleExitPlot(self, entry=None):
        DistributedLawnDecor.DistributedLawnDecor.handleExitPlot(self, entry)
        base.localAvatar.removeShovelRelatedDoId(self.doId)

    def getPlantingText(self):
        plantText = 'hardcoding'
        if self.canBePlanted():
            whatCanBePlanted = GardenGlobals.whatCanBePlanted(
                self.ownerIndex, self.plot)
            plantText = TTLocalizer.GardeningPlant
            if whatCanBePlanted == GardenGlobals.INVALID_TYPE:
                self.notify.warning(
                    'whatCanBePlanted returned INVALID_TYPE for %d %d' %
                    (self.ownerIndex, self.plot))
            elif whatCanBePlanted == GardenGlobals.FLOWER_TYPE:
                plantText = TTLocalizer.GardeningPlantFlower
            elif whatCanBePlanted == GardenGlobals.GAG_TREE_TYPE:
                plantText = TTLocalizer.GardeningPlantTree
            elif whatCanBePlanted == GardenGlobals.STATUARY_TYPE:
                plantText = TTLocalizer.GardeningPlantItem
        return plantText

    def canBePlanted(self):
        return base.localAvatar.doId == self.getOwnerId()

    def plantSomething(self):
        whatCanBePlanted = GardenGlobals.whatCanBePlanted(
            self.ownerIndex, self.plot)
        if whatCanBePlanted == GardenGlobals.INVALID_TYPE:
            self.notify.warning(
                'whatCanBePlanted returned INVALID_TYPE for %d %d' %
                (self.ownerIndex, self.plot))
        elif whatCanBePlanted == GardenGlobals.FLOWER_TYPE:
            self.popupFlowerPlantingGui()
            self.startInteraction()
        elif whatCanBePlanted == GardenGlobals.GAG_TREE_TYPE:
            self.popupTreePlantingGui()
            self.startInteraction()
        elif whatCanBePlanted == GardenGlobals.STATUARY_TYPE:
            self.popupItemPlantingGui()
            self.startInteraction()

    def __handleFlowerPlantingDone(self,
                                   willPlant=0,
                                   recipeStr='',
                                   special=-1):
        self.ignore(self.plantingGuiDoneEvent)
        self.ignore('stoppedAsleep')
        self.plantingGui.destroy()
        self.plantingGui = None
        base.localAvatar.showGardeningGui()
        base.localAvatar.removeShovelRelatedDoId(self.doId)
        successPlanting = False
        if willPlant:
            recipeKey = GardenGlobals.getRecipeKey(recipeStr, special)
            if recipeKey >= 0:
                species, variety = GardenGlobals.getSpeciesVarietyGivenRecipe(
                    recipeKey)
                if species >= 0 and variety >= 0:
                    self.sendUpdate('plantFlower', [species, variety])
                    successPlanting = True
            else:
                self.notify.debug('%s %d is not a valid recipe' %
                                  (recipeStr, special))
                burntBeans = len(recipeStr)
                self.sendUpdate('plantNothing', [burntBeans])
        if successPlanting:
            flowerName = GardenGlobals.getFlowerVarietyName(species, variety)
            stringToShow = TTLocalizer.getResultPlantedSomethingSentence(
                flowerName)
        elif willPlant:
            self.resultDialog = TTDialog.TTDialog(
                style=TTDialog.Acknowledge,
                text=TTLocalizer.ResultPlantedNothing,
                command=self.popupFlowerPlantingGuiAgain)
        else:
            self.finishInteraction()
        return

    def popupFlowerPlantingGui(self):
        base.localAvatar.hideGardeningGui()
        self.acceptOnce(self.plantingGuiDoneEvent,
                        self.__handleFlowerPlantingDone)
        self.plantingGui = PlantingGUI.PlantingGUI(self.plantingGuiDoneEvent)
        self.accept('stoppedAsleep', self.__handleFlowerPlantingDone)

    def resultsCallback(self, value):
        self.notify.debug('value=%d' % value)
        self.resultDialog.destroy()
        self.resultDialog = None
        self.finishInteraction()
        return

    def popupFlowerPlantingGuiAgain(self, value):
        self.notify.debug('value=%d' % value)
        self.resultDialog.destroy()
        self.resultDialog = None
        self.popupFlowerPlantingGui()
        return

    def popupItemPlantingGuiAgain(self, value):
        self.notify.debug('value=%d' % value)
        self.resultDialog.destroy()
        self.resultDialog = None
        self.popupItemPlantingGui()
        return

    def __handleItemPlantingDone(self,
                                 willPlant=0,
                                 recipeStr='',
                                 selectedSpecial=-1):
        self.ignore(self.plantingGuiDoneEvent)
        self.ignore('stoppedAsleep')
        self.plantingGui.destroy()
        self.plantingGui = None
        base.localAvatar.showGardeningGui()
        base.localAvatar.removeShovelRelatedDoId(self.doId)
        gardenSpecials = base.localAvatar.getGardenSpecials()
        special = -1
        if selectedSpecial >= 0:
            special = gardenSpecials[selectedSpecial][0]
        successPlanting = False
        successToonStatue = False
        if willPlant:
            recipeKey = GardenGlobals.getRecipeKey(recipeStr, special)
            if recipeKey >= 0:
                species, variety = GardenGlobals.getSpeciesVarietyGivenRecipe(
                    recipeKey)
                if species >= 0 and variety >= 0:
                    if GardenGlobals.PlantAttributes[species][
                            'plantType'] == GardenGlobals.STATUARY_TYPE:
                        successPlanting = True
                        if species >= 205 and species <= 208:
                            successToonStatue = True
                        else:
                            self.sendUpdate('plantStatuary', [species])
            else:
                self.notify.debug('%s %d is not a valid recipe' %
                                  (recipeStr, special))
                burntBeans = len(recipeStr)
                self.sendUpdate('plantNothing', [burntBeans])
        if successPlanting:
            itemName = GardenGlobals.PlantAttributes[species]['name']
            stringToShow = TTLocalizer.getResultPlantedSomethingSentence(
                itemName)
        elif willPlant:
            self.resultDialog = TTDialog.TTDialog(
                style=TTDialog.Acknowledge,
                text=TTLocalizer.ResultPlantedNothing,
                command=self.popupItemPlantingGuiAgain)
        else:
            self.finishInteraction()
        if successToonStatue:
            self.popupToonStatueSelectionGui(species)
        return

    def popupItemPlantingGui(self):
        base.localAvatar.hideGardeningGui()
        self.acceptOnce(self.plantingGuiDoneEvent,
                        self.__handleItemPlantingDone)
        self.plantingGui = PlantingGUI.PlantingGUI(self.plantingGuiDoneEvent,
                                                   True)
        self.plantingGui.showFirstSpecial()
        self.accept('stoppedAsleep', self.__handleItemPlantingDone)

    def popupToonStatueSelectionGui(self, species):
        base.localAvatar.hideGardeningGui()
        self.acceptOnce(self.toonStatueSelectionDoneEvent,
                        self.__handleToonStatueSelectionDone,
                        extraArgs=[species])
        self.toonStatueSelectionGui = ToonStatueSelectionGUI.ToonStatueSelectionGUI(
            self.toonStatueSelectionDoneEvent, True)
        self.accept('stoppedAsleep', self.__handleToonStatueSelectionDone)

    def popupToonStatueSelectionGuiAgain(self, species):
        self.resultDialog.destroy()
        self.resultDialog = None
        self.popupToonStatueSelectionGui(species)
        return

    def __handleToonStatueSelectionDone(self,
                                        species,
                                        willPlant=0,
                                        recipeStr='',
                                        dnaCode=-1):
        self.ignore(self.toonStatueSelectionDoneEvent)
        self.ignore('stoppedAsleep')
        self.toonStatueSelectionGui.destroy()
        self.toonStatueSelectionGui = None
        base.localAvatar.showGardeningGui()
        base.localAvatar.removeShovelRelatedDoId(self.doId)
        if willPlant:
            self.sendUpdate('plantToonStatuary', [species, dnaCode])
        else:
            self.popupItemPlantingGui()
        return

    def popupTreePlantingGui(self):
        base.localAvatar.hideGardeningGui()
        self.acceptOnce(self.plantingGuiDoneEvent,
                        self.__handleTreePlantingDone)
        self.plantingGui = PlantTreeGUI.PlantTreeGUI(self.plantingGuiDoneEvent)
        self.accept('stoppedAsleep', self.__handleTreePlantingDone)

    def __handleTreePlantingDone(self,
                                 willPlant=False,
                                 gagTrack=None,
                                 gagLevel=None):
        self.ignore(self.plantingGuiDoneEvent)
        self.ignore('stoppedAsleep')
        self.plantingGui.destroy()
        self.plantingGui = None
        base.localAvatar.showGardeningGui()
        base.localAvatar.removeShovelRelatedDoId(self.doId)
        if willPlant:
            self.sendUpdate('plantGagTree', [gagTrack, gagLevel])
        else:
            self.finishInteraction()
        return

    def setMovie(self, mode, avId):
        if mode == GardenGlobals.MOVIE_PLANT:
            self.doPlaceItemTrack(avId)
        elif mode == GardenGlobals.MOVIE_FINISHREMOVING:
            self.doFinishRemovingTrack(avId)
        elif mode == GardenGlobals.MOVIE_PLANT_REJECTED:
            self.doPlantRejectedTrack(avId)

    def doPlantRejectedTrack(self, avId):
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.finishMovies()
        self.movie = Sequence()
        self.movie.append(Func(toon.detachShovel))
        self.movie.append(Func(toon.loop, 'neutral'))
        if avId == localAvatar.doId:
            self.movie.append(Func(self.finishInteraction))
            self.movie.append(Func(self.movieDone))
        self.movie.start()

    def doFinishRemovingTrack(self, avId):
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.finishMovies()
        self.movie = Sequence()
        self.movie.append(Func(toon.detachShovel))
        if self.model:
            pos = self.model.getPos()
            pos.setZ(pos[2] - 1)
            animProp = LerpPosInterval(self.model, 3, self.model.getPos(), pos)
            shrinkProp = LerpScaleInterval(self.model,
                                           3,
                                           scale=self.plotScale,
                                           startScale=0.01)
            objAnimShrink = ParallelEndTogether(animProp, shrinkProp)
            self.movie.append(objAnimShrink)
        self.movie.append(self.stopCamIval(avId))
        self.movie.append(Func(toon.loop, 'neutral'))
        if avId == localAvatar.doId:
            self.movie.append(Func(self.finishInteraction))
            self.movie.append(Func(self.movieDone))
        self.movie.start()

    def doPlaceItemTrack(self, avId, item=None):
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.finishMovies()
        if avId == localAvatar.doId:
            self.startInteraction()
        shovel = toon.attachShovel()
        shovel.hide()
        moveTrack = self.generateToonMoveTrack(toon)
        placeItemTrack = self.generatePlaceItemTrack(toon, item)
        self.movie = Sequence(self.startCamIval(avId), moveTrack,
                              Func(shovel.show), placeItemTrack)
        if avId == localAvatar.doId:
            self.expectingReplacement = 1
            self.movie.append(Func(self.movieDone))
        self.movie.start()

    def generatePlaceItemTrack(self, toon, item):
        sound = loader.loadSfx('phase_5.5/audio/sfx/burrow.ogg')
        sound.setPlayRate(0.5)
        placeItemTrack = Parallel()
        placeItemTrack.append(
            Sequence(
                ActorInterval(toon, 'start-dig'),
                Parallel(
                    ActorInterval(toon, 'loop-dig', loop=1, duration=5.13),
                    Sequence(Wait(0.25),
                             SoundInterval(sound, node=toon, duration=0.55),
                             Wait(0.8),
                             SoundInterval(sound, node=toon, duration=0.55),
                             Wait(1.35),
                             SoundInterval(sound, node=toon, duration=0.55))),
                ActorInterval(toon, 'start-dig', playRate=-1),
                Func(toon.loop, 'neutral'), Func(toon.detachShovel)))
        if self.model:
            pos = self.model.getPos()
            pos.setZ(pos[2] - 1)
            animProp = LerpPosInterval(self.model, 3, pos)
            shrinkProp = LerpScaleInterval(self.model,
                                           3,
                                           scale=0.01,
                                           startScale=self.model.getScale())
            objAnimShrink = ParallelEndTogether(animProp, shrinkProp)
            placeItemTrack.append(objAnimShrink)
        if item:
            placeItemTrack.append(
                Sequence(
                    Func(item.reparentTo, toon.rightHand), Wait(0.55),
                    Func(item.wrtReparentTo, render),
                    Parallel(
                        LerpHprInterval(item,
                                        hpr=self.getHpr(render),
                                        duration=1.2),
                        ProjectileInterval(item,
                                           endPos=self.getPos(render),
                                           duration=1.2,
                                           gravityMult=0.45)),
                    Func(item.removeNode)))
        return placeItemTrack

    def makeMovieNode(self):
        if self.plotType == GardenGlobals.FLOWER_TYPE:
            self.movieNode = self.rotateNode.attachNewNode('moviePos')
            self.movieNode.setPos(0, 3, 0)
            self.movieNode.setH(180)
            self.stick2Ground()
        else:
            DistributedLawnDecor.DistributedLawnDecor.makeMovieNode(self)

    def setBoxDoId(self, boxId, index):
        self.index = index
        if boxId in base.cr.doId2do:
            self.setBox(base.cr.doId2do[boxId])
        else:
            self.acceptOnce('generate-%d' % boxId, self.setBox)

    def setBox(self, box):
        x = GardenGlobals.FLOWER_POS[box.typeIndex][self.index]

        self.setPos(0, 0, 0)
        self.reparentTo(box)
        self.setZ(1.2)
        self.setX(x)

    def stick2Ground(self, *args, **kwargs):
        plotType = GardenGlobals.whatCanBePlanted(self.ownerIndex, self.plot)
        if plotType == GardenGlobals.FLOWER_TYPE:
            return

        return DistributedLawnDecor.DistributedLawnDecor.stick2Ground(
            self, *args, **kwargs)
예제 #31
0
    def getShip(self,
                shipClass,
                style=ShipGlobals.Styles.Undefined,
                logo=ShipGlobals.Logos.Undefined,
                hullDesign=None,
                detailLevel=2,
                wantWheel=True,
                hullMaterial=None,
                sailMaterial=None,
                sailPattern=None,
                prowType=None,
                invertLogo=False):
        Ship = Ship
        import pirates.ship
        modelClass = ShipGlobals.getModelClass(shipClass)
        shipConfig = ShipGlobals.getShipConfig(shipClass)
        if style == ShipGlobals.Styles.Undefined:
            style = shipConfig['defaultStyle']

        complexCustomization = 0
        if sailPattern and sailMaterial and hullMaterial or SailReplace.has_key(
                shipClass):
            complexCustomization = 1

        if not prowType:
            prowType = shipConfig['prow']

        if not hullMaterial:
            hullMaterial = style

        if not sailMaterial:
            if SailReplace.has_key(shipClass):
                sailMaterial = SailReplace[shipClass]
            else:
                sailMaterial = style

        if not sailPattern:
            sailPattern = style

        shipHullTexture = ShipBlueprints.getShipTexture(hullMaterial)
        shipTextureSail = ShipBlueprints.getShipTexture(sailMaterial)
        logoTex = None
        if logo:
            logoTex = ShipBlueprints.getLogoTexture(logo)

        sailPatternTex = None
        if sailPattern:
            sailPatternTex = ShipBlueprints.getSailTexture(sailPattern)

        self.notify.debug('%s %s' % (sailPattern, logo))
        if logo == ShipGlobals.Logos.Undefined:
            logo = shipConfig['sailLogo']

        if logo in ShipGlobals.MAST_LOGO_PLACEMENT_LIST:
            placeLogos = 1
        else:
            placeLogos = 0
        if modelClass <= ShipGlobals.INTERCEPTORL3:
            mastHax = True
        else:
            mastHax = False
        customHull = hullDesign is not None
        if not logo != 0:
            pass
        customMasts = sailPattern != 0
        hull = self.getHull(modelClass, customHull)
        breakAnims = {}
        metaAnims = {}
        hitAnims = {}
        root = NodePath('Ship')
        hull.locators.reparentTo(root)
        charRoot = root.attachNewNode(Character('ShipChar'))
        collisions = root.attachNewNode('collisions')
        lodNode = charRoot.attachNewNode(LODNode('lod'))
        if detailLevel == 0:
            lodNode.node().addSwitch(200, 0)
            lodNode.node().addSwitch(800, 200)
            lodNode.node().addSwitch(100000, 800)
            high = lodNode.attachNewNode('high')
            low = lodNode.attachNewNode('low')
            med = NodePath('med')
            superlow = lodNode.attachNewNode('superlow')
        elif detailLevel == 1:
            lodNode.node().addSwitch(300, 0)
            lodNode.node().addSwitch(1000, 300)
            lodNode.node().addSwitch(2000, 1000)
            lodNode.node().addSwitch(100000, 2000)
            high = lodNode.attachNewNode('high')
            med = lodNode.attachNewNode('med')
            low = lodNode.attachNewNode('low')
            superlow = lodNode.attachNewNode('superlow')
        else:
            lodNode.node().addSwitch(750, 0)
            lodNode.node().addSwitch(3000, 750)
            lodNode.node().addSwitch(8000, 3000)
            lodNode.node().addSwitch(100000, 8000)
            high = lodNode.attachNewNode('high')
            med = lodNode.attachNewNode('med')
            low = lodNode.attachNewNode('low')
            superlow = lodNode.attachNewNode('superlow')
        mastSetup = ShipGlobals.getMastSetup(shipClass)
        for data in [(0, 'location_mainmast_0'), (1, 'location_mainmast_1'),
                     (2, 'location_mainmast_2'), (3, 'location_aftmast*'),
                     (4, 'location_foremast*')]:
            mastData = mastSetup.get(data[0])
            if mastData:
                mast = self.mastSets[mastData[0]].getMastSet(
                    mastData[1] - 1, customMasts)
                mastRoot = hull.locators.find('**/%s' % data[1]).getTransform(
                    hull.locators)
                model = NodePath(mast.charRoot)
                model.setTransform(mastRoot)
                if complexCustomization:
                    model.setTexture(shipTextureSail)

                useLogoTex = logoTex
                if placeLogos:
                    mastNum = data[0]
                    if mastNum not in ShipGlobals.MAST_LOGO_PLACEMENT.get(
                            modelClass):
                        useLogoTex = None

                charBundle = mast.charRoot.getBundle(0)
                if data[0] < 3:
                    for side in ['left', 'right']:
                        ropeNode = hull.locators.find(
                            '**/location_ropeLadder_%s_%s' % (side, data[0]))
                        if ropeNode:
                            transform = ropeNode.getTransform(
                                NodePath(mast.charRoot))
                            charBundle.findChild('def_ladder_0_%s' %
                                                 side).applyFreeze(transform)
                            continue

                if sailPatternTex and useLogoTex:
                    for node in model.findAllMatches('**/sails'):
                        node.setTextureOff(TextureStage.getDefault())
                        node.setTexture(self.colorLayer, sailPatternTex)
                        if invertLogo:
                            node.setTexture(self.logoLayerInv, logoTex)
                        else:
                            node.setTexture(self.logoLayer, logoTex)
                        node.setTexture(self.vertLayer, shipTextureSail)
                        node.setTexture(self.baseLayer, shipTextureSail)

                elif sailPatternTex:
                    for node in model.findAllMatches('**/sails'):
                        node.setTextureOff(TextureStage.getDefault())
                        node.setTexture(self.colorLayer, sailPatternTex)
                        node.setTexture(self.vertLayer, shipTextureSail)
                        node.setTexture(self.baseLayer, shipTextureSail)

                elif useLogoTex:
                    for node in model.findAllMatches('**/sails'):
                        node.setTextureOff(TextureStage.getDefault())
                        if invertLogo:
                            node.setTexture(self.logoLayerNoColorInv, logoTex)
                        else:
                            node.setTexture(self.logoLayerNoColor, logoTex)
                        node.setTexture(self.vertLayer, shipTextureSail)
                        node.setTexture(self.baseLayer, shipTextureSail)

                model.flattenLight()
                if detailLevel == 0:
                    model.find('**/low').copyTo(high)
                    model.find('**/low').copyTo(low)
                    model.find('**/superlow').copyTo(superlow)
                elif detailLevel == 1:
                    model.find('**/med').copyTo(high)
                    model.find('**/med').copyTo(med)
                    low.node().stealChildren(model.find('**/low').node())
                    superlow.node().stealChildren(
                        model.find('**/superlow').node())
                elif detailLevel == 2:
                    high.node().stealChildren(model.find('**/high').node())
                    med.node().stealChildren(model.find('**/med').node())
                    low.node().stealChildren(model.find('**/low').node())
                    superlow.node().stealChildren(
                        model.find('**/superlow').node())

                mastRoot = mast.collisions.find('**/collision_masts')
                if modelClass > ShipGlobals.INTERCEPTORL3 or data[0] != 3:
                    mastCode = str(data[0])
                    mastRoot.setTag('Mast Code', mastCode)
                else:
                    mastRoot.setName('colldision_sub_mast')
                    mastRoot.reparentTo(collisions.find('**/collision_masts'))
                    mastCode = '0'
                for coll in mast.collisions.findAllMatches(
                        '**/collision_sail_*'):
                    coll.setName('Sail-%s' % data[0])
                    coll.setTag('Mast Code', mastCode)

                for coll in mast.collisions.findAllMatches('**/sail_*'):
                    coll.setName('Sail-%s' % data[0])
                    coll.setTag('Mast Code', mastCode)

                collisions.node().stealChildren(mast.collisions.node())
                charBundle = mast.charRoot.getBundle(0)
                if mastHax and data[0] == 3:
                    breakAnims[0][0].storeAnim(
                        charBundle.loadBindAnim(loader.loader,
                                                mast.breakAnim[0], -1,
                                                MastSubset, True), '1')
                    breakAnims[0][1].storeAnim(
                        charBundle.loadBindAnim(loader.loader,
                                                mast.breakAnim[1], -1,
                                                MastSubset, True), '1')
                    tempHit = hitAnims[0]
                    tempHit[0].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.hitAnim,
                                                -1, HitMastSubset, True), '1')
                    tempHit[1].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.hitAnim,
                                                -1, PartSubset(), True), '1')
                else:
                    breakAnims[data[0]] = (AnimControlCollection(),
                                           AnimControlCollection())
                    breakAnims[data[0]][0].storeAnim(
                        charBundle.loadBindAnim(loader.loader,
                                                mast.breakAnim[0], -1,
                                                MastSubset, True), '0')
                    breakAnims[data[0]][1].storeAnim(
                        charBundle.loadBindAnim(loader.loader,
                                                mast.breakAnim[1], -1,
                                                MastSubset, True), '0')
                    tempHit = [
                        AnimControlCollection(),
                        AnimControlCollection()
                    ]
                    tempHit[0].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.hitAnim,
                                                -1, HitMastSubset, True), '0')
                    tempHit[1].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.hitAnim,
                                                -1, PartSubset(), True), '0')
                    hitAnims[data[0]] = tempHit
                for (anim, fileName) in mast.metaAnims.iteritems():
                    if anim not in metaAnims:
                        metaAnims[anim] = AnimControlCollection()

                    if anim not in MissingAnims.get(modelClass, []):
                        ac = charBundle.loadBindAnim(loader.loader, fileName,
                                                     -1, SailSubset, True)
                        if ac:
                            metaAnims[anim].storeAnim(
                                ac, str(metaAnims[anim].getNumAnims()))

                charRoot.node().combineWith(mast.charRoot)
                continue

        if self.wantProws and prowType:
            (highSprit, medSprit, lowSprit) = self.sprits[prowType].getAsset()
            transform = hull.locators.find(
                '**/location_bowsprit').getTransform(hull.locators)
            highSprit.setTransform(transform)
            medSprit.setTransform(transform)
            lowSprit.setTransform(transform)
            highSprit.reparentTo(hull.geoms[0])
            medSprit.reparentTo(hull.geoms[1])
            lowSprit.reparentTo(hull.geoms[2])

        if wantWheel:
            shipWheel = ShipBlueprints.getWheel()
            wheelPoint = hull.locators.find(
                '**/location_wheel;+s').getTransform(hull.locators)
            shipWheel.setTransform(wheelPoint)
            shipWheel.flattenLight()
            shipWheel.find('**/collisions').copyTo(collisions)
            hull.geoms[0].node().stealChildren(
                shipWheel.find('**/high').node())
            hull.geoms[1].node().stealChildren(shipWheel.find('**/med').node())
            hull.geoms[2].node().stealChildren(shipWheel.find('**/low').node())

        if complexCustomization:
            hull.geoms[0].setTexture(shipHullTexture)
            hull.geoms[0].flattenLight()
            hull.geoms[1].setTexture(shipHullTexture)
            hull.geoms[1].flattenLight()
            hull.geoms[2].setTexture(shipHullTexture)
            hull.geoms[2].flattenLight()
            hull.geoms[3].setTexture(shipHullTexture)
            hull.geoms[3].flattenLight()

        high.attachNewNode(ModelNode('non-animated')).node().stealChildren(
            hull.geoms[0].node())
        med.attachNewNode(ModelNode('non-animated')).node().stealChildren(
            hull.geoms[1].node())
        low.attachNewNode(ModelNode('non-animated')).node().stealChildren(
            hull.geoms[2].node())
        superlow.attachNewNode(ModelNode('non-animated')).node().stealChildren(
            hull.geoms[3].node())
        collisions.node().stealChildren(hull.collisions.node())
        hull.locators.stash()
        charRoot.flattenStrong()
        ship = Ship.Ship(shipClass, root, breakAnims, hitAnims, metaAnims,
                         collisions, hull.locators)
        if not complexCustomization:
            ship.char.setTexture(shipHullTexture)

        return ship
class DistributedGardenBox(DistributedLawnDecor.DistributedLawnDecor):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGardenPlot')

    def __init__(self, cr):
        DistributedLawnDecor.DistributedLawnDecor.__init__(self, cr)
        self.plantPath = NodePath('plantPath')
        self.plantPath.reparentTo(self)
        self.plotScale = 1.0
        self.plantingGuiDoneEvent = 'plantingGuiDone'
        self.defaultModel = 'phase_5.5/models/estate/planterC'
        self.flowers = []
        self.flowersData = []

    def announceGenerate(self):
        self.notify.debug('announceGenerate')
        DistributedLawnDecor.DistributedLawnDecor.announceGenerate(self)

    def doModelSetup(self):
        if self.typeIndex == GardenGlobals.BOX_THREE:
            self.defaultModel = 'phase_5.5/models/estate/planterA'
        elif self.typeIndex == GardenGlobals.BOX_TWO:
            self.defaultModel = 'phase_5.5/models/estate/planterC'
        else:
            self.defaultModel = 'phase_5.5/models/estate/planterB'
            self.collSphereOffset = 0.0
            self.collSphereRadius = self.collSphereRadius * 1.41
            self.plotScale = Vec3(1.0, 1.0, 1.0)
            
        self.flowersData = [[0, -1, 0, 1, (49, 0)]] * self.typeIndex
        self.loadFlowers()
        
    def loadFlowers(self):
        for index, flower in enumerate(self.flowersData):
            f = DistributedFlower(self.cr)
            f.doId = index + 500
            f.gardenBox = self
            f.generate()
            f.setWaterLevel(flower[1])
            f.setGrowthLevel(flower[3])
            f.setTypeIndex(flower[-1][0])
            f.setSpecies(flower[-1][0])
            f.setVariety(flower[-1][1])
            f.announceGenerate()
            f.sendUpdate = self.hackedSendUpdate(f)
            f.reparentTo(self)
            f.setZ(self, 1.5)
            f.setX(FLOWER_POS[len(self.flowersData)][index])
            self.flowers.append(f)

    def setupShadow(self):
        pass

    def loadModel(self):
        self.rotateNode = self.plantPath.attachNewNode('rotate')
        self.model = None
        self.model = loader.loadModel(self.defaultModel)
        self.model.setScale(self.plotScale)
        self.model.reparentTo(self.rotateNode)
        self.stick2Ground()
        return

    def handleEnterPlot(self, entry = None):
        pass

    def handleExitPlot(self, entry = None):
        DistributedLawnDecor.DistributedLawnDecor.handleExitPlot(self, entry)

    def setTypeIndex(self, typeIndex):
        self.typeIndex = typeIndex

    def delete(self):
        DistributedLawnDecor.DistributedLawnDecor.delete(self)
        for flower in self.flowers:
            flower.disable()
            flower.delete()
            
        self.flowers = []
        
    def hackedSendUpdate(self, obj):
        def f(fieldName, args):
            doId = obj.doId
            dclass = obj.dclass.getName()
            
            if fieldName.endswith('Plot'):
                return
            
            print 'UPDATE FOR', doId, dclass, fieldName, args
            
        return f
        
예제 #33
0
class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath,
                           ShadowCaster.ShadowCaster):
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'DistributedLawnDecor')

    def __init__(self, cr):
        DistributedNode.DistributedNode.__init__(self, cr)
        NodePath.__init__(self, 'decor')
        ShadowCaster.ShadowCaster.__init__(self, False)
        self.plantPath = NodePath('plantPath')
        self.plantPath.reparentTo(self)
        self.defaultModel = 'phase_9/models/cogHQ/woodCrateB'
        self.messageName = None
        self.model = None
        self.colSphereNode = None
        self.rotateNode = None
        self.collSphereOffset = 0.0
        self.collSphereRadius = 1.0
        self.stickUp = 0.0
        self.movieNode = None
        self.shadowJoint = None
        self.shadowScale = 1
        self.expectingReplacement = 0
        self.movie = None

    def setHeading(self, h):
        self.notify.debug('setting h')
        DistributedNode.DistributedNode.setH(self, h)

    def generateInit(self):
        self.notify.debug('generateInit')
        DistributedNode.DistributedNode.generateInit(self)

    def generate(self):
        self.notify.debug('generate')
        self.reparentTo(render)
        DistributedNode.DistributedNode.generate(self)

    def announceGenerate(self):
        self.notify.debug('announceGenerate')
        DistributedNode.DistributedNode.announceGenerate(self)
        self.doModelSetup()
        self.loadModel()
        self.setupShadow()
        self.makeMovieNode()
        self.stick2Ground()
        self.setupCollision()

    def doModelSetup(self):
        pass

    def disable(self):
        self.notify.debug('disable')
        self.finishMovies()
        self.handleExitPlot()
        self.ignoreAll()
        DistributedNode.DistributedNode.disable(self)
        if hasattr(self, 'nodePath'):
            self.nodePath.detachNode()

    def delete(self):
        self.notify.debug('delete')
        ShadowCaster.ShadowCaster.delete(self)
        self.unloadModel()
        DistributedNode.DistributedNode.delete(self)

    def loadModel(self):
        if not self.rotateNode:
            self.rotateNode = self.plantPath.attachNewNode('rotate')
        self.model = None
        if __dev__:
            self.model = loader.loadModel(self.defaultModel)
            self.model.setScale(0.4, 0.4, 0.1)
            self.model.reparentTo(self.rotateNode)

    def setupShadow(self):
        self.shadowJoint = self.rotateNode.attachNewNode('shadow')
        self.initializeDropShadow(False)
        self.shadowJoint.setScale(self.shadowScale)
        self.setActiveShadow()

    def makeMovieNode(self):
        self.movieNode = self.rotateNode.attachNewNode('moviePos')
        self.movieNode.setPos(0, -3, 0)

    def setupCollision(self):
        self.messageName = self.uniqueName('enterplotSphere')
        self.messageStartName = self.uniqueName('plotSphere')
        self.exitMessageName = self.uniqueName('exitplotSphere')
        if self.collSphereOffset <= 0.1:
            colSphere = CollisionSphere(0, 0, 0, self.collSphereRadius)
        else:
            colSphere = CollisionTube(0, -self.collSphereOffset, 0, 0,
                                      self.collSphereOffset, 0,
                                      self.collSphereRadius)
        colSphere.setTangible(0)
        colNode = CollisionNode(self.messageStartName)
        colNode.addSolid(colSphere)
        colSphereNode = self.attachNewNode(colNode)
        self.colSphereNode = colSphereNode
        self.accept(self.messageName, self.handleEnterPlot)
        self.accept(self.exitMessageName, self.handleExitPlot)

    def handleEnterPlot(self, optional=None):
        self.notify.debug('handleEnterPlot %d' % self.doId)
        self.sendUpdate('plotEntered', [])

    def handleExitPlot(self, optional=None):
        if base.localAvatar.inGardenAction == self:
            base.localAvatar.handleEndPlantInteraction(
                self, replacement=self.expectingReplacement)

    def handleWatering(self):
        self.handleExitPlot()
        base.localAvatar.removeShovelRelatedDoId(self.doId)

    def unloadModel(self):
        if self.model:
            self.model.removeNode()
            del self.model
            self.model = None
        if hasattr(self, 'nodePath') and self.nodePath:
            self.nodePath.removeNode()
            self.nodePath = None
        taskMgr.remove(self.uniqueName('adjust tree'))

    def setPos(self, x, y, z):
        DistributedNode.DistributedNode.setPos(self, x, y, z)
        self.stick2Ground()

    def setPosition(self, x, y, z):
        DistributedNode.DistributedNode.setPos(self, x, y, z)
        self.stick2Ground()

    def stick2Ground(self, taskfooler=0):
        if self.isEmpty():
            return Task.done
        testPath = NodePath('testPath')
        testPath.reparentTo(render)
        cRay = CollisionRay(0.0, 0.0, 40000.0, 0.0, 0.0, -1.0)
        cRayNode = CollisionNode(self.uniqueName('estate-FloorRay'))
        cRayNode.addSolid(cRay)
        cRayNode.setFromCollideMask(OTPGlobals.FloorBitmask)
        cRayNode.setIntoCollideMask(BitMask32.allOff())
        cRayNodePath = testPath.attachNewNode(cRayNode)
        queue = CollisionHandlerQueue()
        picker = CollisionTraverser()
        picker.addCollider(cRayNodePath, queue)
        if self.movieNode:
            testPath.setPos(self.movieNode.getX(render),
                            self.movieNode.getY(render), 0)
            picker.traverse(render)
            if queue.getNumEntries() > 0:
                queue.sortEntries()
                for index in range(queue.getNumEntries()):
                    entry = queue.getEntry(index)
                    if recurseParent(entry.getIntoNode(), 'terrain_DNARoot'):
                        self.movieNode.setZ(entry.getSurfacePoint(self)[2])

        testPath.setPos(self.getX(), self.getY(), 0)
        picker.traverse(render)
        if queue.getNumEntries() > 0:
            queue.sortEntries()
            for index in range(queue.getNumEntries()):
                entry = queue.getEntry(index)
                if recurseParent(entry.getIntoNode(), 'terrain_DNARoot'):
                    self.setZ(
                        entry.getSurfacePoint(render)[2] + self.stickUp + 0.1)
                    self.stickParts()
                    return Task.done

        taskMgr.doMethodLater(1.0, self.stick2Ground,
                              uniqueName('groundsticker'))
        return Task.done

    def stickParts(self):
        pass

    def setPlot(self, plot):
        self.plot = plot

    def setH(self, h):
        DistributedNode.DistributedNode.setH(self, h)

    def getPlot(self):
        return self.plot

    def setOwnerIndex(self, index):
        self.ownerIndex = index

    def getOwnerIndex(self):
        return self.ownerIndex

    def getOwnerId(self):
        retval = 0
        estate = base.cr.doFind('DistributedEstate')
        if estate and hasattr(estate, 'idList') and estate.idList:
            if self.ownerIndex < len(estate.idList):
                retval = estate.idList[self.ownerIndex]
        return retval

    def canBePicked(self):
        retval = True
        self.notify.debug('base.localAvatar.doId : %s' % base.localAvatar.doId)
        self.notify.debug('self.getOwnerId : %s ' % self.getOwnerId())
        self.notify.debug("statue's DoId : %s " % self.doId)
        if not hasattr(base, 'localAvatar'
                       ) or not base.localAvatar.doId == self.getOwnerId():
            retval = False
        return retval

    def allowedToPick(self):
        return True

    def unlockPick(self):
        return True

    def handleRemove(self):
        if not self.canBePicked():
            self.notify.debug("I don't own this item, just returning")
            return
        base.localAvatar.hideShovelButton()
        base.localAvatar.hideWateringCanButton()
        self.startInteraction()
        self.sendUpdate('removeItem', [])

    def generateToonMoveTrack(self, toon):
        node = NodePath('tempNode')
        displacement = Vec3(toon.getPos(render) - self.getPos(render))
        displacement.setZ(0)
        displacement.normalize()
        movieDistance = self.movieNode.getDistance(self.rotateNode)
        displacement *= movieDistance
        node.reparentTo(render)
        node.setPos(displacement + self.getPos(render))
        node.lookAt(self)
        heading = PythonUtil.fitDestAngle2Src(toon.getH(render),
                                              node.getH(render))
        hpr = toon.getHpr(render)
        hpr.setX(heading)
        finalX = node.getX(render)
        finalY = node.getY(render)
        finalZ = node.getZ(render)
        node.removeNode()
        toonTrack = Sequence(
            Parallel(
                ActorInterval(toon, 'walk', loop=True, duration=1),
                Parallel(
                    LerpPosInterval(toon,
                                    1.0,
                                    Point3(finalX, finalY, toon.getZ(render)),
                                    fluid=True,
                                    bakeInStart=False)),
                LerpHprInterval(toon, 1.0, hpr=hpr)),
            Func(toon.loop, 'neutral'))
        return toonTrack

    def startInteraction(self):
        place = base.cr.playGame.getPlace()
        if place:
            place.detectedGardenPlotUse()
            base.localAvatar.setInGardenAction(self)

    def finishInteraction(self):
        if hasattr(base.cr.playGame.getPlace(), 'detectedGardenPlotDone'):
            base.cr.playGame.getPlace().detectedGardenPlotDone()
            self.notify.debug('done interaction')
        else:
            self.notify.warning(
                'base.cr.playGame.getPlace() does not have detectedGardenPlotDone'
            )
        if hasattr(base, 'localAvatar'):
            base.localAvatar.handleEndPlantInteraction(self)

    def startCamIval(self, avId):
        track = Sequence()
        if avId == localAvatar.doId:
            track = Sequence(
                Func(base.localAvatar.disableSmartCameraViews),
                Func(base.localAvatar.setCameraPosForPetInteraction))
        return track

    def stopCamIval(self, avId):
        track = Sequence()
        if avId == localAvatar.doId:
            track = Sequence(
                Func(base.localAvatar.unsetCameraPosForPetInteraction),
                Wait(0.8), Func(base.localAvatar.enableSmartCameraViews))
        return track

    def canBeWatered(self):
        return 0

    def getShovelAction(self):
        return None

    def getShovelCommand(self):
        return None

    def canBePlanted(self):
        return 0

    def movieDone(self):
        self.sendUpdate('movieDone', [])

    def setMovie(self, mode, avId):
        if mode == GardenGlobals.MOVIE_FINISHPLANTING:
            self.doFinishPlantingTrack(avId)
        elif mode == GardenGlobals.MOVIE_REMOVE:
            self.doDigupTrack(avId)

    def finishMovies(self):
        if self.movie:
            self.movie.finish()
            self.movie = None

    def doDigupTrack(self, avId):
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.finishMovies()
        self.model.setTransparency(1)
        self.model.setAlphaScale(1)
        shovel = toon.attachShovel()
        shovel.hide()
        moveTrack = self.generateToonMoveTrack(toon)
        digupTrack = self.generateDigupTrack(toon)
        self.movie = Sequence(self.startCamIval(avId), moveTrack,
                              Func(shovel.show), digupTrack)
        if avId == localAvatar.doId:
            self.expectingReplacement = 1
            self.movie.append(Func(self.movieDone))
        self.movie.start()

    def generateDigupTrack(self, toon):
        sound = loader.loadSfx('phase_5.5/audio/sfx/burrow.ogg')
        sound.setPlayRate(0.5)
        pos = self.model.getPos()
        pos.setZ(pos[2] - 1)
        track = Parallel()
        track.append(
            Sequence(
                ActorInterval(toon, 'start-dig'),
                Parallel(
                    ActorInterval(toon, 'loop-dig', loop=1, duration=5.13),
                    Sequence(Wait(0.25),
                             SoundInterval(sound, node=toon, duration=0.55),
                             Wait(0.8),
                             SoundInterval(sound, node=toon, duration=0.55),
                             Wait(1.35),
                             SoundInterval(sound, node=toon, duration=0.55))),
                ActorInterval(toon, 'start-dig', playRate=-1),
                LerpFunc(self.model.setAlphaScale,
                         fromData=1,
                         toData=0,
                         duration=1), Func(toon.loop, 'neutral'),
                Func(toon.detachShovel)))
        return track

    def doFinishPlantingTrack(self, avId):
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.finishMovies()
        self.movie = Sequence()
        if avId == localAvatar.doId:
            self.startInteraction()
        if self.model:
            self.model.setTransparency(1)
            self.model.setAlphaScale(0)
            self.movie.append(
                LerpFunc(self.model.setAlphaScale,
                         fromData=0,
                         toData=1,
                         duration=3))
        self.movie.append(self.stopCamIval(avId))
        self.movie.append(Func(toon.detachShovel))
        self.movie.append(Func(toon.loop, 'neutral'))
        if avId == localAvatar.doId:
            self.movie.append(Func(self.finishInteraction))
            self.movie.append(Func(self.movieDone))
            if hasattr(self, 'doResultDialog'):
                self.movie.append(Func(self.doResultDialog))
        self.movie.start()

    def interactionDenied(self, avId):
        if avId == localAvatar.doId:
            self.finishInteraction()
예제 #34
0
    def test_door_setup(self):
        parent_np = NodePath('parent_np')
        parent_np.setPosHpr(0, 10, .5, 180, 0, 0)

        door_origin = parent_np.attachNewNode('door_origin')
        door_origin.setPos(10, -25, .5)

        block = 4
        color = Vec4(.842, .167, .361, 1)

        # Set up door_np nodes
        door_np = NodePath('door_np')

        left_hole = door_np.attachNewNode('door_0_hole_left')
        right_hole = door_np.attachNewNode('door_0_hole_right')

        left_door = door_np.attachNewNode('door_0_left')
        right_door = door_np.attachNewNode('door_0_right')

        door_flat = door_np.attachNewNode('door_0_flat')
        door_trigger = door_np.attachNewNode('door_0_trigger')

        DNADoor.setupDoor(door_np, parent_np, door_origin, self.store, block, color)

        # Check if the nodes attributes and parents are correct
        self.assertEqual(door_np.getPos(door_origin), Point3(0, 0, 0))
        self.assertEqual(door_np.getHpr(door_origin), Point3(0, 0, 0))
        self.assertEqual(door_np.getScale(door_origin), Point3(1, 1, 1))

        def verify_color(color1, color2):
            self.assertAlmostEqual(color1.getX(), color2.getX(), places=4)
            self.assertAlmostEqual(color1.getY(), color2.getY(), places=4)
            self.assertAlmostEqual(color1.getZ(), color2.getZ(), places=4)
            self.assertAlmostEqual(color1.getW(), color2.getW(), places=4)

        verify_color(color, door_np.getColor())

        self.assertEqual(left_hole.getParent(), door_flat)
        self.assertEqual(left_hole.getName(), 'doorFrameHoleLeft')

        self.assertEqual(right_hole.getParent(), door_flat)
        self.assertEqual(right_hole.getName(), 'doorFrameHoleRight')

        self.assertEqual(left_door.getParent(), parent_np)
        self.assertEqual(left_door.getName(), 'leftDoor')
        verify_color(color, right_door.getColor())

        self.assertEqual(right_door.getParent(), parent_np)
        self.assertEqual(right_door.getName(), 'rightDoor')
        verify_color(color, right_door.getColor())

        self.assertEqual(door_trigger.getParent(), parent_np)
        self.assertEqual(door_trigger.getName(), 'door_trigger_%d' % block)

        store_np = self.store.getDoorPosHprFromBlockNumber(block)
        self.assertFalse(store_np.isEmpty())

        # Testing the pos is a pain because of decimal precision
        pos = store_np.getPos()
        self.assertAlmostEqual(pos.getX(), -10, places=2)
        self.assertAlmostEqual(pos.getY(), 35, places=2)
        self.assertAlmostEqual(pos.getZ(), 1, places=2)

        # Sometimes getH() returns -180 and others 180
        # Test the modulus (better than abs I guess)
        self.assertEqual(store_np.getH() % 180, 0)
class TexturePainter(DirectObject):
  def __init__(self):
    self.editTexture = None
    self.editModel = None
    
    self.texturePainterStatus = TEXTURE_PAINTER_STATUS_DISABLED
    
    self.paintColor = VBase4D(1,1,1,1)
    self.paintSize = 10
    self.paintEffect = PNMBrush.BEBlend
    self.paintSmooth = True
    self.paintMode = TEXTUREPAINTER_FUNCTION_PAINT_POINT
    
    self.painter = None
  
  # --- creation and destroying of the whole editor ---
  def enableEditor(self):
    ''' create the editor
    change from disabled to enabled'''
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_DISABLED:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_ENABLED
      self.__enableEditor()
    else:
      print "E: TexturePainter.enableEditor: not disabled", self.texturePainterStatus
  
  def disableEditor(self):
    ''' destroy the editor, automatically stop the editor and painting
    change from enabled to disabled'''
    # try stopping if more advanced mode
    #if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
    #  self.stopEditor()
    
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_ENABLED:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_DISABLED
      self.__disableEditor()
    else:
      print "E: TexturePainter.disableEditor: not enabled", self.texturePainterStatus
  
  # --- 
  def startEditor(self, editModel, editTexture, backgroundShader=MODEL_COLOR_SHADER):
    ''' prepare to paint
    change from enabled to initialized'''
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_ENABLED:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_INITIALIZED
      self.__startEditor(editModel, editTexture, backgroundShader)
    else:
      print "E: TexturePainter.startEditor: not enabled", self.texturePainterStatus
  
  def stopEditor(self):
    ''' stop painting, automatically stop painting
    change from initialized to enabled'''
    #if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
    #  self.stopPaint()
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_ENABLED
      return self.__stopEditor()
    else:
      print "E: TexturePainter.startEditor: not initialized", self.texturePainterStatus
  
  """ # this is not externally callable
  # ---
  def startPaint(self):
    ''' start painting on the model
    change from initialized to running '''
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_INITIALIZED:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_RUNNING
      self.__startPaint()
    else:
      print "E: TexturePainter.startPaint: not enabled", self.texturePainterStatus"""
  
  def stopPaint(self):
    ''' stop painting
    change from running to initialized '''
    if self.texturePainterStatus == TEXTURE_PAINTER_STATUS_RUNNING:
      self.texturePainterStatus = TEXTURE_PAINTER_STATUS_INITIALIZED
      self.__stopPaint()
    else:
      print "E: TexturePainter.stopPaint: not running", self.texturePainterStatus
  
  
  # --- brush settings for painting ---
  ''' changing brush settings is possible all the time '''
  def setBrushSettings(self, color, size, smooth, effect):
    #print "I: TexturePainter.setBrushSettings", color, size, smooth, effect
    self.paintColor = color
    self.paintSize = size
    self.paintEffect = effect
    self.paintSmooth = smooth
    if effect in [PNMBrush.BESet, PNMBrush.BEBlend, PNMBrush.BEDarken, PNMBrush.BELighten]:
      self.brush = PNMBrush.makeSpot(color, size, smooth, effect)
      #if self.paintModel:
      if self.painter:
        self.painter.setPen(self.brush)
  
  def getBrushSettings(self):
    return self.paintColor,self.paintSize,self.paintSmooth,self.paintEffect
  
  def setPaintMode(self, newMode):
    self.paintMode = newMode
    # clear last point if mode changed
    if newMode == TEXTUREPAINTER_FUNCTION_PAINT_POINT or \
       newMode == TEXTUREPAINTER_FUNCTION_READ:
      self.lastPoint = None
  
  def getPaintMode(self):
    return self.paintMode
  
  
  
  def __enableEditor(self):
    ''' create the background rendering etc., but the model is not yet defined '''
    print "I: TexturePainter.__enableEditor"
    # the buffer the model with the color texture is rendered into
    self.modelColorBuffer = None
    self.modelColorCam = None
    # the buffer the picked position color is rendered into
    self.colorPickerBuffer = None
    self.colorPickerCam = None
    # create the buffers
    self.__createBuffer()
    
    # when the window is resized, the background buffer etc must be updated.
    self.accept("window-event", self.__windowEvent)
    
    # some debugging stuff
    self.accept("v", base.bufferViewer.toggleEnable)
    self.accept("V", base.bufferViewer.toggleEnable)
  
  def __disableEditor(self):
    print "I: TexturePainter.__disableEditor"
    
    self.__destroyBuffer()
    
    # ignore window-event and debug
    self.ignoreAll()
  
  def __windowEvent(self, win=None):
    ''' when the editor is enabled, update the buffers etc. when the window
    is resized '''
    print "I: TexturePainter.windowEvent"
    
    # with a fixed backgroudn buffer size this is not needed anymore
    
    if False:
      #if self.texturePainterStatus != TEXTURE_PAINTER_STATUS_DISABLED:
      if self.modelColorBuffer:
        if WindowManager.activeWindow:
          # on window resize there seems to be never a active window
          win = WindowManager.activeWindow.win
        else:
          win = base.win
        if self.modelColorBuffer.getXSize() != win.getXSize() or self.modelColorBuffer.getYSize() != win.getYSize():
          '''print "  - window resized",\
              self.modelColorBuffer.getXSize(),\
              win.getXSize(),\
              self.modelColorBuffer.getYSize(),\
              win.getYSize()'''
          # if the buffer size doesnt match the window size (window has been resized)
          self.__destroyBuffer()
          self.__createBuffer()
          self.__updateModel()
      else:
        print "W: TexturePainter.__windowEvent: no buffer"
        self.__createBuffer()
  
  def __createBuffer(self):
    ''' create the buffer we render in the background into '''
    print "I: TexturePainter.__createBuffer"
    # the window has been modified
    if WindowManager.activeWindow:
      # on window resize there seems to be never a active window
      win = WindowManager.activeWindow.win
    else:
      win = base.win
    
    # get the window size
    self.windowSizeX = win.getXSize()
    self.windowSizeY = win.getYSize()
    
    # create a buffer in which we render the model using a shader
    self.paintMap = Texture()
    # 1.5.4 cant handle non power of 2 buffers
    self.modelColorBuffer = createOffscreenBuffer(-3, TEXTUREPAINTER_BACKGROUND_BUFFER_RENDERSIZE[0], TEXTUREPAINTER_BACKGROUND_BUFFER_RENDERSIZE[1]) #self.windowSizeX, self.windowSizeY)
    self.modelColorBuffer.addRenderTexture(self.paintMap, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPColor)
    self.modelColorCam = base.makeCamera(self.modelColorBuffer, lens=base.cam.node().getLens(), sort=1)
    
    # Create a small buffer for the shader program that will fetch the point from the texture made
    # by the self.modelColorBuffer
    self.colorPickerImage = PNMImage()
    self.colorPickerTex = Texture()
    self.colorPickerBuffer = base.win.makeTextureBuffer("color picker buffer", 2, 2, self.colorPickerTex, True)
    
    self.colorPickerScene = NodePath('color picker scene')
    
    self.colorPickerCam = base.makeCamera(self.colorPickerBuffer, lens=base.cam.node().getLens(), sort=2)
    self.colorPickerCam.reparentTo(self.colorPickerScene)
    self.colorPickerCam.setY(-2)
    
    cm = CardMaker('color picker scene card')
    cm.setFrameFullscreenQuad()
    pickerCard = self.colorPickerScene.attachNewNode(cm.generate())
    
    loadPicker = NodePath(PandaNode('pointnode'))
    loadPicker.setShader(Shader.make(COLOR_PICKER_SHADER), 10001)
    
    # Feed the paintmap from the paintBuffer to the shader and initial mouse positions
    self.colorPickerScene.setShaderInput('paintmap', self.paintMap)
    self.colorPickerScene.setShaderInput('mousepos', 0, 0, 0, 1)
    self.colorPickerCam.node().setInitialState(loadPicker.getState())
  
  def __destroyBuffer(self):
    print "I: TexturePainter.__destroyBuffer"
    if self.modelColorBuffer:
      
      # Destroy the buffer
      base.graphicsEngine.removeWindow(self.modelColorBuffer)
      self.modelColorBuffer = None
      # Remove the camera
      self.modelColorCam.removeNode()
      del self.modelColorCam
      
      self.colorPickerScene.removeNode()
      del self.colorPickerScene
      # remove cam
      self.colorPickerCam.removeNode()
      del self.colorPickerCam
      # Destroy the buffer
      base.graphicsEngine.removeWindow(self.colorPickerBuffer)
      self.colorPickerBuffer = None
      
      del self.colorPickerTex
      del self.colorPickerImage
  
  def __startEditor(self, editModel, editTexture, backgroundShader=MODEL_COLOR_SHADER):
    print "I: TexturePainter.__startEditor"
    
    # this is needed as on startup the editor may not have had a window etc.
    self.__windowEvent()
    
    if not editModel or not editTexture:
      print "W: TexturePainter.__startEditor: model or texture invalid", editModel, editTexture
      return False
    
    self.editModel = editModel
    self.editTexture = editTexture
    self.editImage = None
    self.backgroundShader = backgroundShader
    
    if type(self.editTexture) == Texture:
      # if the image to modify is a texture, create a pnmImage which we modify
      self.editImage = PNMImage()
      # copy the image from the texture to the working layer
      self.editTexture.store(self.editImage)
    else:
      self.editImage = self.editTexture
    
    # create the brush for painting
    self.painter = PNMPainter(self.editImage)
    self.setBrushSettings( *self.getBrushSettings() )
    
    self.__updateModel()
    
    # start edit
    messenger.send(EVENT_TEXTUREPAINTER_STARTEDIT)
    
    for startEvent in TEXTUREPAINTER_START_PAINT_EVENTS:
      self.accept(startEvent, self.__startPaint)
    for stopEvent in TEXTUREPAINTER_STOP_PAINT_EVENTS:
      self.accept(stopEvent, self.__stopPaint)
    
    self.modelColorCam.node().copyLens(WindowManager.activeWindow.camera.node().getLens())
    
    taskMgr.add(self.__paintTask, 'paintTask')
    
    #modelModificator.toggleEditmode(False)
    
    self.isPainting = False
  
  def __stopEditor(self):
    print "I: TexturePainter.__stopEditor"
    for startEvent in TEXTUREPAINTER_START_PAINT_EVENTS:
      self.ignore(startEvent)
    for stopEvent in TEXTUREPAINTER_STOP_PAINT_EVENTS:
      self.ignore(stopEvent)
    
    taskMgr.remove('paintTask')
    # stop edit end
    
    # must be reset before we loose the properties
    if self.editModel and self.editTexture and self.editImage:
      try:
        # hide the model from cam 2
        self.editModel.hide(BitMask32.bit(1))
        self.editModel = None
      except:
        print "E: TexturePainter.__stopEditor: the model has already been deleted"
    
    # stop edit
    messenger.send(EVENT_TEXTUREPAINTER_STOPEDIT)
    
    self.editImage = None
    self.editTexture = None
    self.painter = None
    self.brush = None
    
    #modelModificator.toggleEditmode(True)
    
  
  def __updateModel(self):
    if self.editModel:
      # create a image with the same size of the texture
      textureSize = (self.editTexture.getXSize(), self.editTexture.getYSize())
      
      # create a dummy node, where we setup the parameters for the background rendering
      loadPaintNode = NodePath(PandaNode('paintnode'))
      loadPaintNode.setShader(Shader.make(self.backgroundShader), 10001)
      loadPaintNode.setShaderInput('texsize', textureSize[0], textureSize[1], 0, 0)
      
      # copy the state onto the camera
      self.modelColorCam.node().setInitialState(loadPaintNode.getState())
      
      # the camera gets a special bitmask, to show/hide models from it
      self.modelColorCam.node().setCameraMask(BitMask32.bit(1))
      
      if False:
        # doesnt work, but would be nicer (not messing with the default render state)
        
        hiddenNode = NodePath(PandaNode('hiddennode'))
        hiddenNode.hide(BitMask32.bit(1))
        showTroughNode = NodePath(PandaNode('showtroughnode'))
        showTroughNode.showThrough(BitMask32.bit(1))
        
        self.modelColorCam.node().setTagStateKey('show-on-backrender-cam')
        self.modelColorCam.node().setTagState('False', hiddenNode.getState())
        self.modelColorCam.node().setTagState('True', showTroughNode.getState())
        
        render.setTag('show-on-backrender-cam', 'False')
        self.editModel.setTag('show-on-backrender-cam', 'True')
      else:
        # make only the model visible to the background camera
        render.hide(BitMask32.bit(1))
        self.editModel.showThrough(BitMask32.bit(1))
  
  # --- start the paint tasks ---
  def __startPaint(self):
    self.isPainting = True
  
  def __stopPaint(self):
    self.isPainting = False
  
  # --- modification tasks ---
  def __textureUpdateTask(self, task=None):
    ''' modify the texture using the edited image
    '''
    if type(self.editTexture) == Texture:
      self.editTexture.load(self.editImage)
    
    if task: # task may be None
      return task.again
  
  def __paintTask(self, task):
    #print "I: TexturePainter.__paintTask:"
    
    if not WindowManager.activeWindow or not WindowManager.activeWindow.mouseWatcherNode.hasMouse():
      '''print "  - abort:", WindowManager.activeWindow
      if WindowManager.activeWindow:
        print "  - mouse:", WindowManager.activeWindow.mouseWatcherNode.hasMouse()'''
      return task.cont
    
    
    # update the camera according to the active camera
    #self.modelColorCam.setMat(render, WindowManager.activeWindow.camera.getMat(render))
    
    mpos = base.mouseWatcherNode.getMouse()
    x_ratio = min( max( ((mpos.getX()+1)/2), 0), 1)
    y_ratio = min( max( ((mpos.getY()+1)/2), 0), 1)
    mx = int(x_ratio*self.windowSizeX)
    my = self.windowSizeY - int(y_ratio*self.windowSizeY)
    
    self.colorPickerScene.setShaderInput('mousepos', x_ratio, y_ratio, 0, 1)
    
    if self.colorPickerTex.hasRamImage():
      self.colorPickerTex.store(self.colorPickerImage)
      
      # get the color below the mousepick from the rendered frame
      r = self.colorPickerImage.getRedVal(0,0)
      g = self.colorPickerImage.getGreenVal(0,0)
      b = self.colorPickerImage.getBlueVal(0,0)
      # calculate uv-texture position from the color
      x = r + ((b%16)*256)
      y = g + ((b//16)*256)
      
      if self.isPainting:
        self.__paintPixel(x,y)
        self.__textureUpdateTask()
    else:
      # this might happen if no frame has been rendered yet since creation of the texture
      print "W: TexturePainter.__paintTask: colorPickerTex.hasRamMipmapImage() =", self.colorPickerTex.hasRamImage()
    
    return task.cont
  
  def __paintPixel(self, x, y):
    ''' paint at x/y with the defined settings '''
    
    imageMaxX = self.editImage.getXSize()
    imageMaxY = self.editImage.getYSize()
    def inImage(x,y):
      ''' is the given x/y position within the image '''
      return ((imageMaxX > x >= 0) and (imageMaxY > y >= 0))
    
    # how smooth should be painted
    if self.paintSmooth:
      # a smooth brush
      hardness = 1.0
    else:
      # a hard brush
      hardness = 0.1
    hardness = min(1.0, max(0.05, hardness))
    
    # the paint radius
    radius = int(round(self.paintSize/2.0))
    radiusSquare = float(radius*radius)
    
    # a function to get the brush color/strength, depending on the radius
    def getBrushColor(diffPosX, diffPosY):
      distance = diffPosX**2 + diffPosY**2
      brushStrength = (1 - (min(distance, radiusSquare) / radiusSquare)) / hardness
      return min(1.0, max(0.0, brushStrength))
    
    if inImage(x,y):
      if self.paintMode == TEXTUREPAINTER_FUNCTION_PAINT_POINT:
        if self.paintEffect in [PNMBrush.BESet, PNMBrush.BEBlend, PNMBrush.BEDarken, PNMBrush.BELighten]:
          # render a spot into the texture
          self.painter.drawPoint(x, y)
        
        elif self.paintEffect in [TEXTUREPAINTER_BRUSH_FLATTEN, TEXTUREPAINTER_BRUSH_SMOOTH, TEXTUREPAINTER_BRUSH_RANDOMIZE]:
          
          if self.paintEffect == TEXTUREPAINTER_BRUSH_SMOOTH:
            # calculate average values
            data = dict()
            smoothRadius = 2
            for dx in xrange(-radius, radius+1):
              for dy in xrange(-radius, radius+1):
                if inImage(x+dx,y+dy):
                  average = VBase4D(0)
                  dividor = 0
                  for px in xrange(-smoothRadius,smoothRadius+1):
                    for py in xrange(-smoothRadius,smoothRadius+1):
                      if inImage(x+dx+px,y+dy+py):
                        average += self.editImage.getXelA(x+dx+px,y+dy+py)
                        dividor += 1
                  average /= float(dividor)
                  data[(x+dx,y+dy)] = average
            
            # save to image
            for (px,py), newValue in data.items():
              currentValue = self.editImage.getXelA(px,py)
              diffValue = currentValue - newValue
              
              dx = px - x
              dy = py - y
              
              
              multiplier = getBrushColor(dx, dy)
              print dx, dy, multiplier
              '''if self.paintSmooth:
                multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
              else:
                # not sure if this is correct
                multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
              
              '''r = currentValue.getX() * (1-multiplier*self.paintColor.getX()) + diffValue.getX() * multiplier*self.paintColor.getX()
              g = currentValue.getY() * (1-multiplier*self.paintColor.getY()) + diffValue.getY() * multiplier*self.paintColor.getY()
              b = currentValue.getZ() * (1-multiplier*self.paintColor.getZ()) + diffValue.getZ() * multiplier*self.paintColor.getZ()
              a = currentValue.getW() * (1-multiplier*self.paintColor.getW()) + diffValue.getW() * multiplier*self.paintColor.getW()'''
              r = currentValue.getX() - multiplier * diffValue.getX()
              g = currentValue.getY() - multiplier * diffValue.getY()
              b = currentValue.getZ() - multiplier * diffValue.getZ()
              a = currentValue.getW() - multiplier * diffValue.getW()
              if self.editImage.hasAlpha():
                self.editImage.setXelA(px,py,VBase4D(r,g,b,a))
              else:
                self.editImage.setXel(px,py,VBase3D(r,g,b))
              
              #self.editImage.setXelA(x,y,value)
            
          if self.paintEffect == TEXTUREPAINTER_BRUSH_FLATTEN:
            dividor = 0
            average = VBase4D(0)
            for dx in xrange(-radius, radius+1):
              for dy in xrange(-radius, radius+1):
                if inImage(x+dx,y+dy):
                  multiplier = getBrushColor(dx, dy)
                  '''if self.paintSmooth:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
                  else:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
                  dividor += multiplier
                  average += self.editImage.getXelA(x+dx,y+dy) * multiplier
            average /= dividor
            for dx in xrange(-radius, radius+1):
              for dy in xrange(-radius, radius+1):
                if inImage(x+dx,y+dy):
                  multiplier = getBrushColor(dx, dy)
                  '''if self.paintSmooth:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
                  else:
                    # not sure if this is correct
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
                  currentValue = self.editImage.getXelA(x+dx,y+dy)
                  r = currentValue.getX() * (1-multiplier*self.paintColor.getX()) + average.getX() * multiplier*self.paintColor.getX()
                  g = currentValue.getY() * (1-multiplier*self.paintColor.getY()) + average.getY() * multiplier*self.paintColor.getY()
                  b = currentValue.getZ() * (1-multiplier*self.paintColor.getZ()) + average.getZ() * multiplier*self.paintColor.getZ()
                  a = currentValue.getW() * (1-multiplier*self.paintColor.getW()) + average.getW() * multiplier*self.paintColor.getW()
                  if self.editImage.hasAlpha():
                    self.editImage.setXelA(x+dx,y+dy,VBase4D(r,g,b,a))
                  else:
                    self.editImage.setXel(x+dx,y+dy,VBase3D(r,g,b))
          
          elif self.paintEffect == TEXTUREPAINTER_BRUSH_RANDOMIZE:
            for dx in xrange(-radius, radius+1):
              for dy in xrange(-radius, radius+1):
                if inImage(x+dx,y+dy):
                  r = VBase4D(random.random()*self.paintColor.getX()-self.paintColor.getX()/2.,
                             random.random()*self.paintColor.getY()-self.paintColor.getY()/2.,
                             random.random()*self.paintColor.getZ()-self.paintColor.getZ()/2.,
                             random.random()*self.paintColor.getW()-self.paintColor.getW()/2.)
                  multiplier = getBrushColor(dx, dy)
                  '''if self.paintSmooth:
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy))) / (radius*radius)
                  else:
                    # not sure if this is correct
                    multiplier = ((radius-math.fabs(dx))*(radius-math.fabs(dy)))'''
                  currentValue = self.editImage.getXelA(x+dx,y+dy)
                  self.editImage.setXelA(x+dx,y+dy,currentValue+r*multiplier)
      
      elif self.paintMode == TEXTUREPAINTER_FUNCTION_READ:
        if inImage(x,y):
          col = self.editImage.getXelA(x,y)
          if self.editImage.hasAlpha():
            self.paintColor = VBase4D(col[0], col[1], col[2], col[3])
          else:
            self.paintColor = VBase4D(col[0], col[1], col[2], 1.0)
          messenger.send(EVENT_TEXTUREPAINTER_BRUSHCHANGED)
      
      elif self.paintMode == TEXTUREPAINTER_FUNCTION_PAINT_LINE:
        if self.lastPoint != None:
          self.painter.drawLine(x, y, self.lastPoint[0], self.lastPoint[1])
      
      elif self.paintMode == TEXTUREPAINTER_FUNCTION_PAINT_RECTANGLE:
        if self.lastPoint != None:
          self.painter.drawRectangle(x, y, self.lastPoint[0], self.lastPoint[1])
      
      self.lastPoint = (x,y)
예제 #36
0
class DistributedButterfly(DistributedObject.DistributedObject):
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'DistributedButterfly')
    id = 0
    wingTypes = ('wings_1', 'wings_2', 'wings_3', 'wings_4', 'wings_5',
                 'wings_6')
    yellowColors = (Vec4(1, 1, 1, 1), Vec4(0.2, 0, 1, 1), Vec4(0.8, 0, 1, 1))
    whiteColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0, 0.8, 0.8,
                                              1), Vec4(0.9, 0.4, 0.6, 1),
                   Vec4(0.9, 0.4, 0.4, 1), Vec4(0.8, 0.5, 0.9,
                                                1), Vec4(0.4, 0.1, 0.7, 1))
    paleYellowColors = (Vec4(0.8, 0, 0.8, 1), Vec4(0.6, 0.6, 0.9,
                                                   1), Vec4(0.7, 0.6, 0.9, 1),
                        Vec4(0.8, 0.6, 0.9, 1), Vec4(0.9, 0.6, 0.9,
                                                     1), Vec4(1, 0.6, 0.9, 1))
    shadowScaleBig = Point3(0.07, 0.07, 0.07)
    shadowScaleSmall = Point3(0.01, 0.01, 0.01)

    def __init__(self, cr):
        DistributedObject.DistributedObject.__init__(self, cr)
        self.fsm = ClassicFSM.ClassicFSM('DistributedButterfly', [
            State.State('off', self.enterOff, self.exitOff,
                        ['Flying', 'Landed']),
            State.State('Flying', self.enterFlying, self.exitFlying,
                        ['Landed']),
            State.State('Landed', self.enterLanded, self.exitLanded,
                        ['Flying'])
        ], 'off', 'off')
        self.butterfly = None
        self.butterflyNode = None
        self.curIndex = 0
        self.destIndex = 0
        self.time = 0.0
        self.ival = None
        self.fsm.enterInitialState()
        return

    def generate(self):
        DistributedObject.DistributedObject.generate(self)
        if self.butterfly:
            return
        self.butterfly = Actor.Actor()
        self.butterfly.loadModel('phase_4/models/props/SZ_butterfly-mod')
        self.butterfly.loadAnims({
            'flutter':
            'phase_4/models/props/SZ_butterfly-flutter',
            'glide':
            'phase_4/models/props/SZ_butterfly-glide',
            'land':
            'phase_4/models/props/SZ_butterfly-land'
        })
        index = self.doId % len(self.wingTypes)
        chosenType = self.wingTypes[index]
        node = self.butterfly.getGeomNode()
        for type in self.wingTypes:
            wing = node.find('**/' + type)
            if type != chosenType:
                wing.removeNode()
            else:
                if index == 0 or index == 1:
                    color = self.yellowColors[self.doId %
                                              len(self.yellowColors)]
                elif index == 2 or index == 3:
                    color = self.whiteColors[self.doId % len(self.whiteColors)]
                elif index == 4:
                    color = self.paleYellowColors[self.doId %
                                                  len(self.paleYellowColors)]
                else:
                    color = Vec4(1, 1, 1, 1)
                wing.setColor(color)

        self.butterfly2 = Actor.Actor(other=self.butterfly)
        self.butterfly.enableBlend(blendType=PartBundle.BTLinear)
        self.butterfly.loop('flutter')
        self.butterfly.loop('land')
        self.butterfly.loop('glide')
        rng = RandomNumGen.RandomNumGen(self.doId)
        playRate = 0.6 + 0.8 * rng.random()
        self.butterfly.setPlayRate(playRate, 'flutter')
        self.butterfly.setPlayRate(playRate, 'land')
        self.butterfly.setPlayRate(playRate, 'glide')
        self.butterfly2.setPlayRate(playRate, 'flutter')
        self.butterfly2.setPlayRate(playRate, 'land')
        self.butterfly2.setPlayRate(playRate, 'glide')
        self.glideWeight = rng.random() * 2
        lodNode = LODNode('butterfly-node')
        lodNode.addSwitch(100, 40)
        lodNode.addSwitch(40, 0)
        self.butterflyNode = NodePath(lodNode)
        self.butterfly2.setH(180.0)
        self.butterfly2.reparentTo(self.butterflyNode)
        self.butterfly.setH(180.0)
        self.butterfly.reparentTo(self.butterflyNode)
        self.__initCollisions()
        self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow')
        self.dropShadow.setColor(0, 0, 0, 0.3)
        self.dropShadow.setPos(0, 0.1, -0.05)
        self.dropShadow.setScale(self.shadowScaleBig)
        self.dropShadow.reparentTo(self.butterfly)

    def disable(self):
        self.butterflyNode.reparentTo(hidden)
        if self.ival != None:
            self.ival.finish()
        self.__ignoreAvatars()
        DistributedObject.DistributedObject.disable(self)
        return

    def delete(self):
        self.butterfly.cleanup()
        self.butterfly = None
        self.butterfly2.cleanup()
        self.butterfly2 = None
        self.butterflyNode.removeNode()
        self.__deleteCollisions()
        self.ival = None
        del self.fsm
        DistributedObject.DistributedObject.delete(self)
        return

    def uniqueButterflyName(self, name):
        DistributedButterfly.id += 1
        return name + '-%d' % DistributedButterfly.id

    def __detectAvatars(self):
        self.accept('enter' + self.cSphereNode.getName(),
                    self.__handleCollisionSphereEnter)

    def __ignoreAvatars(self):
        self.ignore('enter' + self.cSphereNode.getName())

    def __initCollisions(self):
        self.cSphere = CollisionSphere(0.0, 1.0, 0.0, 3.0)
        self.cSphere.setTangible(0)
        self.cSphereNode = CollisionNode(
            self.uniqueButterflyName('cSphereNode'))
        self.cSphereNode.addSolid(self.cSphere)
        self.cSphereNodePath = self.butterflyNode.attachNewNode(
            self.cSphereNode)
        self.cSphereNodePath.hide()
        self.cSphereNode.setCollideMask(ToontownGlobals.WallBitmask)

    def __deleteCollisions(self):
        del self.cSphere
        del self.cSphereNode
        self.cSphereNodePath.removeNode()
        del self.cSphereNodePath

    def __handleCollisionSphereEnter(self, collEntry):
        self.sendUpdate('avatarEnter', [])

    def setArea(self, playground, area):
        self.playground = playground
        self.area = area

    def setState(self, stateIndex, curIndex, destIndex, time, timestamp):
        self.curIndex = curIndex
        self.destIndex = destIndex
        self.time = time
        self.fsm.request(ButterflyGlobals.states[stateIndex],
                         [globalClockDelta.localElapsedTime(timestamp)])

    def enterOff(self, ts=0.0):
        if self.butterflyNode != None:
            self.butterflyNode.reparentTo(hidden)
        return

    def exitOff(self):
        if self.butterflyNode != None:
            self.butterflyNode.reparentTo(render)
        return

    def enterFlying(self, ts):
        self.__detectAvatars()
        curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][
            self.curIndex]
        destPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][
            self.destIndex]
        flyHeight = max(
            curPos[2],
            destPos[2]) + ButterflyGlobals.BUTTERFLY_HEIGHT[self.playground]
        curPosHigh = Point3(curPos[0], curPos[1], flyHeight)
        destPosHigh = Point3(destPos[0], destPos[1], flyHeight)
        if ts <= self.time:
            flyTime = self.time - (
                ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground] +
                ButterflyGlobals.BUTTERFLY_LANDING[self.playground])
            self.butterflyNode.setPos(curPos)
            self.dropShadow.show()
            self.dropShadow.setScale(self.shadowScaleBig)
            oldHpr = self.butterflyNode.getHpr()
            self.butterflyNode.headsUp(destPos)
            newHpr = self.butterflyNode.getHpr()
            self.butterflyNode.setHpr(oldHpr)
            takeoffShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_TAKEOFF[
                self.playground]
            landShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_LANDING[
                self.playground]
            self.butterfly2.loop('flutter')
            self.ival = Sequence(
                Parallel(
                    LerpPosHprInterval(
                        self.butterflyNode,
                        ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground],
                        curPosHigh, newHpr),
                    LerpAnimInterval(
                        self.butterfly,
                        ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground],
                        'land', 'flutter'),
                    LerpAnimInterval(
                        self.butterfly,
                        ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground],
                        None,
                        'glide',
                        startWeight=0,
                        endWeight=self.glideWeight),
                    Sequence(
                        LerpScaleInterval(self.dropShadow,
                                          takeoffShadowT,
                                          self.shadowScaleSmall,
                                          startScale=self.shadowScaleBig),
                        HideInterval(self.dropShadow))),
                LerpPosInterval(self.butterflyNode, flyTime, destPosHigh),
                Parallel(
                    LerpPosInterval(
                        self.butterflyNode,
                        ButterflyGlobals.BUTTERFLY_LANDING[self.playground],
                        destPos),
                    LerpAnimInterval(
                        self.butterfly,
                        ButterflyGlobals.BUTTERFLY_LANDING[self.playground],
                        'flutter', 'land'),
                    LerpAnimInterval(
                        self.butterfly,
                        ButterflyGlobals.BUTTERFLY_LANDING[self.playground],
                        None,
                        'glide',
                        startWeight=self.glideWeight,
                        endWeight=0),
                    Sequence(
                        Wait(ButterflyGlobals.BUTTERFLY_LANDING[
                            self.playground] - landShadowT),
                        ShowInterval(self.dropShadow),
                        LerpScaleInterval(self.dropShadow,
                                          landShadowT,
                                          self.shadowScaleBig,
                                          startScale=self.shadowScaleSmall))),
                name=self.uniqueName('Butterfly'))
            self.ival.start(ts)
        else:
            self.ival = None
            self.butterflyNode.setPos(destPos)
            self.butterfly.setControlEffect('land', 1.0)
            self.butterfly.setControlEffect('flutter', 0.0)
            self.butterfly.setControlEffect('glide', 0.0)
            self.butterfly2.loop('land')
        return

    def exitFlying(self):
        self.__ignoreAvatars()
        if self.ival != None:
            self.ival.finish()
            self.ival = None
        return

    def enterLanded(self, ts):
        self.__detectAvatars()
        curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][
            self.curIndex]
        self.butterflyNode.setPos(curPos)
        self.dropShadow.show()
        self.dropShadow.setScale(self.shadowScaleBig)
        self.butterfly.setControlEffect('land', 1.0)
        self.butterfly.setControlEffect('flutter', 0.0)
        self.butterfly.setControlEffect('glide', 0.0)
        self.butterfly2.pose(
            'land', random.randrange(self.butterfly2.getNumFrames('land')))
        return None

    def exitLanded(self):
        self.__ignoreAvatars()
        return None
예제 #37
0
class AreaMap(Map):
    def __init__(self, area):
        Map.__init__(self, "map-" + area.getName())
        self.capturePoints = {}
        mapNode = area.getMapNode()
        if mapNode and not mapNode.isEmpty():
            geom = mapNode.getChild(0)
            geom.setScale(mapNode.getScale())
            geom.flattenStrong()
            mapNode.setScale(1)
            self.worldNode = mapNode
            self.map = self.worldNode.copyTo(NodePath())
            (a, b) = self.map.getTightBounds()
            diff = b - a
            h = diff[1]
            w = diff[0]
        else:
            self.worldNode = area
            self.map = NodePath("no map found")
            (a, b) = self.worldNode.geom.getTightBounds()
            diff = b - a
            h = diff[1]
            w = diff[0]
        ratio = h / w
        if ratio < 0.98999999999999999:
            normalScale = 2 / w
            screenScale = 1
        else:
            normalScale = 2 / h
            screenScale = 0.75
        self.map.clearTransform()
        self.map.show()
        self.screenNode = NodePath("Minimap-screenNode")
        self.screenNode.setP(90)
        self.screenNode.setScale(screenScale * normalScale)
        self.screenNode.hide()
        self.map.reparentTo(self.screenNode)
        self.mapOverlay = self.map.attachNewNode("mapOverlay")
        self.mapOverlay.wrtReparentTo(self.screenNode)
        self.radarTransformNode = NodePath("radarTransform")
        self.radarTransformNode.setScale(self.worldNode.getScale()[0])
        self.map.instanceTo(self.radarTransformNode)
        localAvatar.guiMgr.addMinimap(self)
        if self.allowOnScreen():
            self.addObject(MinimapFootprint(area))

        if self.allowOnScreen():
            if area.getUniqueId() not in [LocationIds.RAVENS_COVE_ISLAND]:
                for shop in area.getShopNodes():
                    uid = shop.getTag("Uid")
                    shopType = shop.getTag("ShopType")
                    self.addObject(MinimapShop(uid, shop, shopType))

            self.map.findAllMatches("**/=Holiday").stash()
            if base.cr.newsManager:
                for holiday in base.cr.newsManager.getHolidayList():
                    self.handleHolidayStarted(area, HolidayGlobals.getHolidayName(holiday))

        self.zoomLevels = area.getZoomLevels()
        self.accept("landMapRadarAxisChanged", self.setRadarAxis)

    def destroy(self):
        self.ignore("landMapRadarAxisChanged")
        if hasattr(base, "localAvatar"):
            localAvatar.guiMgr.removeMinimap(self)

        for holiday in self.capturePoints.keys():
            zones = self.capturePoints.pop(holiday, {})
            for object in zones.itervalues():
                self.removeObject(object)

        Map.destroy(self)

    def allowOnScreen(self):
        return self.map.find("minimap-card").isEmpty()

    def getZoomLevels(self):
        return self.zoomLevels

    def getWorldNode(self):
        return self.worldNode

    def getScreenNode(self):
        return self.screenNode

    def getOverlayNode(self):
        return self.mapOverlay

    def getCapturePoint(self, holidayId, zone):
        if self.capturePoints.has_key(holidayId):
            return self.capturePoints[holidayId][zone]

    def updateTask(self, task):
        self.update()
        return task.cont

    def update(self):
        for obj in self.objects:
            obj.updateOnMap(self)

    def addObject(self, object):
        Map.addObject(self, object)
        mapNode = object.getMapNode()
        mapNode.reparentTo(self.map, sort=object.SORT)
        object.getOverlayNode().reparentTo(self.mapOverlay, sort=object.SORT)
        object.addedToMap(self)

    def removeObject(self, object):
        Map.removeObject(self, object)
        object.getMapNode().detachNode()
        object.getOverlayNode().detachNode()
        object.removedFromMap(self)

    def updateRadarTransform(self, av):
        if self.radarAxis == Options.RadarAxisMap:
            self.radarTransformNode.setPosHprScale(-av.getPos(self.worldNode), VBase3(0), VBase3(1))
        else:
            holdHpr = av.getHpr()
            av.setH(camera.getH(render) - self.worldNode.getH(render))
            self.radarTransformNode.setTransform(self.worldNode.getTransform(av))
            av.setHpr(holdHpr)
        localAvatar.guiMgr.radarGui.updateDial(self)

    def getRadarNode(self):
        return self.radarTransformNode

    def handleHolidayStarted(self, area, holiday):
        self.map.findAllMatches("**/=Holiday=%s;+s" % (holiday,)).unstash()
        for node in area.getCapturePointNodes(holiday):
            zones = self.capturePoints.setdefault(holiday, {})
            zone = int(node.getTag("Zone"))
            if zone not in zones:
                object = MinimapCapturePoint(node, holiday, zone)
                zones[zone] = object
                self.addObject(object)
                continue

    handleHolidayStarted = report(types=["frameCount", "args"], dConfigParam="minimap")(handleHolidayStarted)

    def handleHolidayEnded(self, area, holiday, override=False):
        if holiday in InvasionGlobals.INVASION_IDS and not override:
            taskMgr.doMethodLater(10, self.handleInvasionEnded, "handleInvasionEnded", extraArgs=[area, holiday])
        else:
            self.map.findAllMatches("**/=Holiday=%s;+s" % (holiday,)).stash()
            for object in self.capturePoints.pop(holiday, {}).itervalues():
                self.removeObject(object)

    handleHolidayEnded = report(types=["frameCount", "args"], dConfigParam="minimap")(handleHolidayEnded)

    def handleInvasionEnded(self, area, holiday):
        if not localAvatar.guiMgr.invasionScoreboard:
            self.map.findAllMatches("**/=Holiday=%s;+s" % (holiday,)).stash()
            for object in self.capturePoints.pop(holiday, {}).itervalues():
                self.removeObject(object)
class DistributedGardenPlot(DistributedLawnDecor.DistributedLawnDecor):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGardenPlot')

    def __init__(self, cr):
        DistributedLawnDecor.DistributedLawnDecor.__init__(self, cr)
        self.plantPath = NodePath('plantPath')
        self.plantPath.reparentTo(self)
        self.plotScale = 1.0
        self.plantingGuiDoneEvent = 'plantingGuiDone'
        self.toonStatueSelectionDoneEvent = 'toonStatueSelectionDone'
        self.defaultModel = 'phase_5.5/models/estate/dirt_mound'
        self.colorScaler = Vec4(1, 1, 1, 1)
        self.plantingGui = None

    def delete(self):
        if self.plantingGui:
            self.plantingGui.destroy()
            self.plantingGui = None
        DistributedLawnDecor.DistributedLawnDecor.delete(self)

    def announceGenerate(self):
        self.plotType = GardenGlobals.whatCanBePlanted(self.ownerIndex, self.plot)
        self.stickUp = 0.0
        if self.getOwnerId() != localAvatar.doId:
            self.defaultModel = None
        elif self.plotType == GardenGlobals.FLOWER_TYPE:
            self.collSphereRadius = 2.0
            self.collSphereOffset = 0.0
            self.plotScale = 0.7
            self.stickUp = 1.1
        elif self.plotType == GardenGlobals.GAG_TREE_TYPE:
            self.collSphereRadius = 3.0
            self.plotScale = 1.5
            self.colorScaler = Vec4(1.0, 1.0, 1.0, 1)
        elif self.plotType == GardenGlobals.STATUARY_TYPE:
            self.collSphereRadius = 3.0
            self.plotScale = 0.075
            self.stickUp = -0.0
            self.defaultModel = 'phase_5.5/models/estate/garden_slab'
        else:
            self.collSphereOffset = 0.0
        self.notify.debug('announceGenerate')
        DistributedLawnDecor.DistributedLawnDecor.announceGenerate(self)

    def loadModel(self):
        self.rotateNode = self.plantPath.attachNewNode('rotate')
        self.model = None
        if self.defaultModel:
            self.model = loader.loadModel(self.defaultModel)
            if type(self.plotScale) == types.TupleType:
                self.model.setScale(*self.plotScale)
            else:
                self.model.setScale(self.plotScale)
            self.model.reparentTo(self.rotateNode)
            self.model.setColorScale(self.colorScaler)
            self.stick2Ground()

    def setupShadow(self):
        pass

    def getShovelCommand(self):
        return self.plantSomething

    def getShovelAction(self):
        return self.getPlantingText()

    def handleEnterPlot(self, entry = None):
        dist = self.getDistance(localAvatar)
        if self.canBePlanted():
            base.localAvatar.addShovelRelatedDoId(self.doId)

    def handleExitPlot(self, entry = None):
        DistributedLawnDecor.DistributedLawnDecor.handleExitPlot(self, entry)
        base.localAvatar.removeShovelRelatedDoId(self.doId)

    def getPlantingText(self):
        plantText = 'hardcoding'
        if self.canBePlanted():
            whatCanBePlanted = GardenGlobals.whatCanBePlanted(self.ownerIndex, self.plot)
            plantText = TTLocalizer.GardeningPlant
            if whatCanBePlanted == GardenGlobals.INVALID_TYPE:
                self.notify.warning('whatCanBePlanted returned INVALID_TYPE for %d %d' % (self.ownerIndex, self.plot))
            elif whatCanBePlanted == GardenGlobals.FLOWER_TYPE:
                plantText = TTLocalizer.GardeningPlantFlower
            elif whatCanBePlanted == GardenGlobals.GAG_TREE_TYPE:
                plantText = TTLocalizer.GardeningPlantTree
            elif whatCanBePlanted == GardenGlobals.STATUARY_TYPE:
                plantText = TTLocalizer.GardeningPlantItem
        return plantText

    def canBePlanted(self):
        retval = True
        if not base.localAvatar.doId == self.getOwnerId():
            retval = False
        return retval

    def plantSomething(self):
        whatCanBePlanted = GardenGlobals.whatCanBePlanted(self.ownerIndex, self.plot)
        if whatCanBePlanted == GardenGlobals.INVALID_TYPE:
            self.notify.warning('whatCanBePlanted returned INVALID_TYPE for %d %d' % (self.ownerIndex, self.plot))
        elif whatCanBePlanted == GardenGlobals.FLOWER_TYPE:
            self.popupFlowerPlantingGui()
            self.startInteraction()
        elif whatCanBePlanted == GardenGlobals.GAG_TREE_TYPE:
            self.popupTreePlantingGui()
            self.startInteraction()
        elif whatCanBePlanted == GardenGlobals.STATUARY_TYPE:
            self.popupItemPlantingGui()
            self.startInteraction()

    def __handleFlowerPlantingDone(self, willPlant = 0, recipeStr = '', special = -1):
        self.ignore(self.plantingGuiDoneEvent)
        self.ignore('stoppedAsleep')
        self.plantingGui.destroy()
        self.plantingGui = None
        base.localAvatar.showGardeningGui()
        base.localAvatar.removeShovelRelatedDoId(self.doId)
        successPlanting = False
        if willPlant:
            recipeKey = GardenGlobals.getRecipeKey(recipeStr, special)
            if recipeKey >= 0:
                species, variety = GardenGlobals.getSpeciesVarietyGivenRecipe(recipeKey)
                if species >= 0 and variety >= 0:
                    self.sendUpdate('plantFlower', [species, variety])
                    successPlanting = True
            else:
                self.notify.debug('%s %d is not a valid recipe' % (recipeStr, special))
                burntBeans = len(recipeStr)
                self.sendUpdate('plantNothing', [burntBeans])
        if successPlanting:
            flowerName = GardenGlobals.getFlowerVarietyName(species, variety)
            stringToShow = TTLocalizer.getResultPlantedSomethingSentence(flowerName)
        elif willPlant:
            self.resultDialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=TTLocalizer.ResultPlantedNothing, command=self.popupFlowerPlantingGuiAgain)
        else:
            self.finishInteraction()

    def popupFlowerPlantingGui(self):
        base.localAvatar.hideGardeningGui()
        self.acceptOnce(self.plantingGuiDoneEvent, self.__handleFlowerPlantingDone)
        self.plantingGui = PlantingGUI.PlantingGUI(self.plantingGuiDoneEvent)
        self.accept('stoppedAsleep', self.__handleFlowerPlantingDone)

    def resultsCallback(self, value):
        self.notify.debug('value=%d' % value)
        self.resultDialog.destroy()
        self.resultDialog = None
        self.finishInteraction()

    def popupFlowerPlantingGuiAgain(self, value):
        self.notify.debug('value=%d' % value)
        self.resultDialog.destroy()
        self.resultDialog = None
        self.popupFlowerPlantingGui()

    def popupItemPlantingGuiAgain(self, value):
        self.notify.debug('value=%d' % value)
        self.resultDialog.destroy()
        self.resultDialog = None
        self.popupItemPlantingGui()

    def __handleItemPlantingDone(self, willPlant = 0, recipeStr = '', selectedSpecial = -1):
        self.ignore(self.plantingGuiDoneEvent)
        self.ignore('stoppedAsleep')
        self.plantingGui.destroy()
        self.plantingGui = None
        base.localAvatar.showGardeningGui()
        base.localAvatar.removeShovelRelatedDoId(self.doId)
        gardenSpecials = base.localAvatar.getGardenSpecials()
        special = -1
        if selectedSpecial >= 0:
            special = gardenSpecials[selectedSpecial][0]
        successPlanting = False
        successToonStatue = False
        if willPlant:
            recipeKey = GardenGlobals.getRecipeKey(recipeStr, special)
            if recipeKey >= 0:
                species, variety = GardenGlobals.getSpeciesVarietyGivenRecipe(recipeKey)
                if species >= 0 and variety >= 0:
                    if GardenGlobals.PlantAttributes[species]['plantType'] == GardenGlobals.STATUARY_TYPE:
                        successPlanting = True
                        if 205 <= species <= 208:
                            successToonStatue = True
                        else:
                            self.sendUpdate('plantStatuary', [species])
            else:
                self.notify.debug('%s %d is not a valid recipe' % (recipeStr, special))
                burntBeans = len(recipeStr)
                self.sendUpdate('plantNothing', [burntBeans])
        if successPlanting:
            itemName = GardenGlobals.PlantAttributes[species]['name']
            stringToShow = TTLocalizer.getResultPlantedSomethingSentence(itemName)
        elif willPlant:
            self.resultDialog = TTDialog.TTDialog(style=TTDialog.Acknowledge, text=TTLocalizer.ResultPlantedNothing, command=self.popupItemPlantingGuiAgain)
        else:
            self.finishInteraction()
        if successToonStatue:
            self.popupToonStatueSelectionGui(species)

    def popupItemPlantingGui(self):
        base.localAvatar.hideGardeningGui()
        self.acceptOnce(self.plantingGuiDoneEvent, self.__handleItemPlantingDone)
        self.plantingGui = PlantingGUI.PlantingGUI(self.plantingGuiDoneEvent, True)
        self.plantingGui.showFirstSpecial()
        self.accept('stoppedAsleep', self.__handleItemPlantingDone)

    def popupToonStatueSelectionGui(self, species):
        base.localAvatar.hideGardeningGui()
        self.acceptOnce(self.toonStatueSelectionDoneEvent, self.__handleToonStatueSelectionDone, extraArgs=[species])
        self.toonStatueSelectionGui = ToonStatueSelectionGUI.ToonStatueSelectionGUI(self.toonStatueSelectionDoneEvent, True)
        self.accept('stoppedAsleep', self.__handleToonStatueSelectionDone)

    def popupToonStatueSelectionGuiAgain(self, species):
        self.resultDialog.destroy()
        self.resultDialog = None
        self.popupToonStatueSelectionGui(species)

    def __handleToonStatueSelectionDone(self, species, willPlant = 0, recipeStr = '', dnaCode = -1):
        self.ignore(self.toonStatueSelectionDoneEvent)
        self.ignore('stoppedAsleep')
        self.toonStatueSelectionGui.destroy()
        self.toonStatueSelectionGui = None
        base.localAvatar.showGardeningGui()
        base.localAvatar.removeShovelRelatedDoId(self.doId)
        if willPlant:
            self.sendUpdate('plantToonStatuary', [species, dnaCode])
        else:
            self.popupItemPlantingGui()

    def popupTreePlantingGui(self):
        base.localAvatar.hideGardeningGui()
        self.acceptOnce(self.plantingGuiDoneEvent, self.__handleTreePlantingDone)
        self.plantingGui = PlantTreeGUI.PlantTreeGUI(self.plantingGuiDoneEvent)
        self.accept('stoppedAsleep', self.__handleTreePlantingDone)

    def __handleTreePlantingDone(self, willPlant = False, gagTrack = None, gagLevel = None):
        self.ignore(self.plantingGuiDoneEvent)
        self.ignore('stoppedAsleep')
        self.plantingGui.destroy()
        self.plantingGui = None
        base.localAvatar.showGardeningGui()
        base.localAvatar.removeShovelRelatedDoId(self.doId)
        if willPlant:
            self.sendUpdate('plantGagTree', [gagTrack, gagLevel])
        else:
            self.finishInteraction()

    def setMovie(self, mode, avId):
        if mode == GardenGlobals.MOVIE_PLANT:
            self.doPlaceItemTrack(avId)
        elif mode == GardenGlobals.MOVIE_FINISHREMOVING:
            self.doFinishRemovingTrack(avId)
        elif mode == GardenGlobals.MOVIE_PLANT_REJECTED:
            self.doPlantRejectedTrack(avId)

    def doPlantRejectedTrack(self, avId):
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.finishMovies()
        self.movie = Sequence()
        self.movie.append(Func(toon.detachShovel))
        self.movie.append(Func(toon.loop, 'neutral'))
        if avId == localAvatar.doId:
            self.movie.append(Func(self.finishInteraction))
            self.movie.append(Func(self.movieDone))
        self.movie.start()

    def doFinishRemovingTrack(self, avId):
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.finishMovies()
        self.movie = Sequence()
        self.movie.append(Func(toon.detachShovel))
        if self.model:
            pos = self.model.getPos()
            pos.setZ(pos[2] - 1)
            animProp = LerpPosInterval(self.model, 3, self.model.getPos(), pos)
            shrinkProp = LerpScaleInterval(self.model, 3, scale=self.plotScale, startScale=0.01)
            objAnimShrink = ParallelEndTogether(animProp, shrinkProp)
            self.movie.append(objAnimShrink)
        self.movie.append(self.stopCamIval(avId))
        self.movie.append(Func(toon.loop, 'neutral'))
        if avId == localAvatar.doId:
            self.movie.append(Func(self.finishInteraction))
            self.movie.append(Func(self.movieDone))
        self.movie.start()

    def doPlaceItemTrack(self, avId, item = None):
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.finishMovies()
        if avId == localAvatar.doId:
            self.startInteraction()
        shovel = toon.attachShovel()
        shovel.hide()
        moveTrack = self.generateToonMoveTrack(toon)
        placeItemTrack = self.generatePlaceItemTrack(toon, item)
        self.movie = Sequence(self.startCamIval(avId), moveTrack, Func(shovel.show), placeItemTrack)
        if avId == localAvatar.doId:
            self.expectingReplacement = 1
            self.movie.append(Func(self.movieDone))
        self.movie.start()

    def generatePlaceItemTrack(self, toon, item):
        sound = loader.loadSfx('phase_5.5/audio/sfx/burrow.ogg')
        sound.setPlayRate(0.5)
        placeItemTrack = Parallel()
        placeItemTrack.append(Sequence(ActorInterval(toon, 'start-dig'), Parallel(ActorInterval(toon, 'loop-dig', loop=1, duration=5.13), Sequence(Wait(0.25), SoundInterval(sound, node=toon, duration=0.55), Wait(0.8), SoundInterval(sound, node=toon, duration=0.55), Wait(1.35), SoundInterval(sound, node=toon, duration=0.55))), ActorInterval(toon, 'start-dig', playRate=-1), Func(toon.loop, 'neutral'), Func(toon.detachShovel)))
        if self.model:
            pos = self.model.getPos()
            pos.setZ(pos[2] - 1)
            animProp = LerpPosInterval(self.model, 3, pos)
            shrinkProp = LerpScaleInterval(self.model, 3, scale=0.01, startScale=self.model.getScale())
            objAnimShrink = ParallelEndTogether(animProp, shrinkProp)
            placeItemTrack.append(objAnimShrink)
        if item:
            placeItemTrack.append(Sequence(Func(item.reparentTo, toon.rightHand), Wait(0.55), Func(item.wrtReparentTo, render), Parallel(LerpHprInterval(item, hpr=self.getHpr(render), duration=1.2), ProjectileInterval(item, endPos=self.getPos(render), duration=1.2, gravityMult=0.45)), Func(item.removeNode)))
        return placeItemTrack

    def makeMovieNode(self):
        if self.plotType == GardenGlobals.FLOWER_TYPE:
            self.movieNode = self.rotateNode.attachNewNode('moviePos')
            self.movieNode.setPos(0, 3, 0)
            self.movieNode.setH(180)
            self.stick2Ground()
        else:
            DistributedLawnDecor.DistributedLawnDecor.makeMovieNode(self)
class DistributedButterfly(DistributedObject.DistributedObject):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedButterfly')
    id = 0
    wingTypes = ('wings_1', 'wings_2', 'wings_3', 'wings_4', 'wings_5', 'wings_6')
    yellowColors = (Vec4(1, 1, 1, 1), Vec4(0.2, 0, 1, 1), Vec4(0.8, 0, 1, 1))
    whiteColors = (Vec4(0.8, 0, 0.8, 1),
     Vec4(0, 0.8, 0.8, 1),
     Vec4(0.9, 0.4, 0.6, 1),
     Vec4(0.9, 0.4, 0.4, 1),
     Vec4(0.8, 0.5, 0.9, 1),
     Vec4(0.4, 0.1, 0.7, 1))
    paleYellowColors = (Vec4(0.8, 0, 0.8, 1),
     Vec4(0.6, 0.6, 0.9, 1),
     Vec4(0.7, 0.6, 0.9, 1),
     Vec4(0.8, 0.6, 0.9, 1),
     Vec4(0.9, 0.6, 0.9, 1),
     Vec4(1, 0.6, 0.9, 1))
    shadowScaleBig = Point3(0.07, 0.07, 0.07)
    shadowScaleSmall = Point3(0.01, 0.01, 0.01)

    def __init__(self, cr):
        DistributedObject.DistributedObject.__init__(self, cr)
        self.fsm = ClassicFSM.ClassicFSM('DistributedButterfly', [State.State('off', self.enterOff, self.exitOff, ['Flying', 'Landed']), State.State('Flying', self.enterFlying, self.exitFlying, ['Landed']), State.State('Landed', self.enterLanded, self.exitLanded, ['Flying'])], 'off', 'off')
        self.butterfly = None
        self.butterflyNode = None
        self.curIndex = 0
        self.destIndex = 0
        self.time = 0.0
        self.ival = None
        self.fsm.enterInitialState()
        return

    def generate(self):
        DistributedObject.DistributedObject.generate(self)
        if self.butterfly:
            return
        self.butterfly = Actor.Actor()
        self.butterfly.loadModel('phase_4/models/props/SZ_butterfly-mod')
        self.butterfly.loadAnims({'flutter': 'phase_4/models/props/SZ_butterfly-flutter',
         'glide': 'phase_4/models/props/SZ_butterfly-glide',
         'land': 'phase_4/models/props/SZ_butterfly-land'})
        index = self.doId % len(self.wingTypes)
        chosenType = self.wingTypes[index]
        node = self.butterfly.getGeomNode()
        for type in self.wingTypes:
            wing = node.find('**/' + type)
            if type != chosenType:
                wing.removeNode()
            else:
                if index == 0 or index == 1:
                    color = self.yellowColors[self.doId % len(self.yellowColors)]
                elif index == 2 or index == 3:
                    color = self.whiteColors[self.doId % len(self.whiteColors)]
                elif index == 4:
                    color = self.paleYellowColors[self.doId % len(self.paleYellowColors)]
                else:
                    color = Vec4(1, 1, 1, 1)
                wing.setColor(color)

        self.butterfly2 = Actor.Actor(other=self.butterfly)
        self.butterfly.enableBlend(blendType=PartBundle.BTLinear)
        self.butterfly.loop('flutter')
        self.butterfly.loop('land')
        self.butterfly.loop('glide')
        rng = RandomNumGen.RandomNumGen(self.doId)
        playRate = 0.6 + 0.8 * rng.random()
        self.butterfly.setPlayRate(playRate, 'flutter')
        self.butterfly.setPlayRate(playRate, 'land')
        self.butterfly.setPlayRate(playRate, 'glide')
        self.butterfly2.setPlayRate(playRate, 'flutter')
        self.butterfly2.setPlayRate(playRate, 'land')
        self.butterfly2.setPlayRate(playRate, 'glide')
        self.glideWeight = rng.random() * 2
        lodNode = LODNode('butterfly-node')
        lodNode.addSwitch(100, 40)
        lodNode.addSwitch(40, 0)
        self.butterflyNode = NodePath(lodNode)
        self.butterfly2.setH(180.0)
        self.butterfly2.reparentTo(self.butterflyNode)
        self.butterfly.setH(180.0)
        self.butterfly.reparentTo(self.butterflyNode)
        self.__initCollisions()
        self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow')
        self.dropShadow.setColor(0, 0, 0, 0.3)
        self.dropShadow.setPos(0, 0.1, -0.05)
        self.dropShadow.setScale(self.shadowScaleBig)
        self.dropShadow.reparentTo(self.butterfly)

    def disable(self):
        self.butterflyNode.reparentTo(hidden)
        if self.ival != None:
            self.ival.finish()
        self.__ignoreAvatars()
        DistributedObject.DistributedObject.disable(self)
        return

    def delete(self):
        self.butterfly.cleanup()
        self.butterfly = None
        self.butterfly2.cleanup()
        self.butterfly2 = None
        self.butterflyNode.removeNode()
        self.__deleteCollisions()
        self.ival = None
        del self.fsm
        DistributedObject.DistributedObject.delete(self)
        return

    def uniqueButterflyName(self, name):
        DistributedButterfly.id += 1
        return name + '-%d' % DistributedButterfly.id

    def __detectAvatars(self):
        self.accept('enter' + self.cSphereNode.getName(), self.__handleCollisionSphereEnter)

    def __ignoreAvatars(self):
        self.ignore('enter' + self.cSphereNode.getName())

    def __initCollisions(self):
        self.cSphere = CollisionSphere(0.0, 1.0, 0.0, 3.0)
        self.cSphere.setTangible(0)
        self.cSphereNode = CollisionNode(self.uniqueButterflyName('cSphereNode'))
        self.cSphereNode.addSolid(self.cSphere)
        self.cSphereNodePath = self.butterflyNode.attachNewNode(self.cSphereNode)
        self.cSphereNodePath.hide()
        self.cSphereNode.setCollideMask(ToontownGlobals.WallBitmask)

    def __deleteCollisions(self):
        del self.cSphere
        del self.cSphereNode
        self.cSphereNodePath.removeNode()
        del self.cSphereNodePath

    def __handleCollisionSphereEnter(self, collEntry):
        self.sendUpdate('avatarEnter', [])

    def setArea(self, playground, area):
        self.playground = playground
        self.area = area

    def setState(self, stateIndex, curIndex, destIndex, time, timestamp):
        self.curIndex = curIndex
        self.destIndex = destIndex
        self.time = time
        self.fsm.request(ButterflyGlobals.states[stateIndex], [globalClockDelta.localElapsedTime(timestamp)])

    def enterOff(self, ts = 0.0):
        if self.butterflyNode != None:
            self.butterflyNode.reparentTo(hidden)
        return

    def exitOff(self):
        if self.butterflyNode != None:
            self.butterflyNode.reparentTo(render)
        return

    def enterFlying(self, ts):
        self.__detectAvatars()
        curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.curIndex]
        destPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.destIndex]
        flyHeight = max(curPos[2], destPos[2]) + ButterflyGlobals.BUTTERFLY_HEIGHT[self.playground]
        curPosHigh = Point3(curPos[0], curPos[1], flyHeight)
        destPosHigh = Point3(destPos[0], destPos[1], flyHeight)
        if ts <= self.time:
            flyTime = self.time - (ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground] + ButterflyGlobals.BUTTERFLY_LANDING[self.playground])
            self.butterflyNode.setPos(curPos)
            self.dropShadow.show()
            self.dropShadow.setScale(self.shadowScaleBig)
            oldHpr = self.butterflyNode.getHpr()
            self.butterflyNode.headsUp(destPos)
            newHpr = self.butterflyNode.getHpr()
            self.butterflyNode.setHpr(oldHpr)
            takeoffShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground]
            landShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_LANDING[self.playground]
            self.butterfly2.loop('flutter')
            self.ival = Sequence(Parallel(LerpPosHprInterval(self.butterflyNode, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], curPosHigh, newHpr), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], 'land', 'flutter'), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], None, 'glide', startWeight=0, endWeight=self.glideWeight), Sequence(LerpScaleInterval(self.dropShadow, takeoffShadowT, self.shadowScaleSmall, startScale=self.shadowScaleBig), HideInterval(self.dropShadow))), LerpPosInterval(self.butterflyNode, flyTime, destPosHigh), Parallel(LerpPosInterval(self.butterflyNode, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], destPos), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], 'flutter', 'land'), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], None, 'glide', startWeight=self.glideWeight, endWeight=0), Sequence(Wait(ButterflyGlobals.BUTTERFLY_LANDING[self.playground] - landShadowT), ShowInterval(self.dropShadow), LerpScaleInterval(self.dropShadow, landShadowT, self.shadowScaleBig, startScale=self.shadowScaleSmall))), name=self.uniqueName('Butterfly'))
            self.ival.start(ts)
        else:
            self.ival = None
            self.butterflyNode.setPos(destPos)
            self.butterfly.setControlEffect('land', 1.0)
            self.butterfly.setControlEffect('flutter', 0.0)
            self.butterfly.setControlEffect('glide', 0.0)
            self.butterfly2.loop('land')
        return

    def exitFlying(self):
        self.__ignoreAvatars()
        if self.ival != None:
            self.ival.finish()
            self.ival = None
        return

    def enterLanded(self, ts):
        self.__detectAvatars()
        curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.curIndex]
        self.butterflyNode.setPos(curPos)
        self.dropShadow.show()
        self.dropShadow.setScale(self.shadowScaleBig)
        self.butterfly.setControlEffect('land', 1.0)
        self.butterfly.setControlEffect('flutter', 0.0)
        self.butterfly.setControlEffect('glide', 0.0)
        self.butterfly2.pose('land', random.randrange(self.butterfly2.getNumFrames('land')))
        return None

    def exitLanded(self):
        self.__ignoreAvatars()
        return None
예제 #40
0
def getBackgroundSet(menuItem, frame, arrowhead):
	item = menuItem.item
	kind = item['kind']
	txt = item['txt']
	grphcs = []
	slctrs = ['menu '+kind]
	if 'class' in item: # class after kind: class has higher priority
		slctrs.append('.'+item['class'])
	if 'id' in item: # id after class: id has higher priority
		slctrs.append('#'+item['id'])
	style = getStyle(slctrs, menuItem.cssFName)
	if 'enter-sound' in style: loadSound(menuItem, menuItem.getEnterEvent(), style, 'enter-sound')
	if 'exit-sound' in style: loadSound(menuItem, menuItem.getExitEvent(), style, 'exit-sound')
	if 'press-sound' in style: loadSound(menuItem, menuItem.getPressEvent(MouseButton.one()), style, 'press-sound')
	if 'release-sound' in style: loadSound(menuItem, menuItem.getReleaseEvent(MouseButton.one()), style, 'release-sound')
	if 'drag-sound' in style: loadSound(menuItem, None, style, 'drag-sound')
	for state in STATES:
		slctrs = ['menu '+kind+' :'+stateName[state].lower()]
		if 'class' in item: # class after kind: class has higher priority
			slctrs.append('.'+item['class']+' :'+stateName[state].lower())
		if 'id' in item: # id after class: id has higher priority
			slctrs.append('#'+item['id']+' :'+stateName[state].lower())
		style = getStyle(slctrs, menuItem.cssFName)
		# Want to add more style properties?
		# Do it here:
		# Match style keys here to property names in .ccss
		fontSize = style['font-size']
		bevel = style['bevel']*fontSize
		font  = style['font']
		color = style['color']
		tn = TextNode(txt)
		tn.setText(txt)
		tn.setFont(loader.loadFont(font))
		tn.setSlant(style['slant'])
		tn.setTextColor(color)
		tn.setShadow(*style['shadow-offset'])
		tn.setShadowColor(*style['shadow-color'])
		NodePath(tn).setScale(fontSize)
		sHolder = NodePath(PandaNode('sHolder'))
		sHolder.attachNewNode(tn)
		grphcs.append(sHolder)
		sHolder.attachNewNode(tn)
		borderColor = style['border-Color']
		thk = style['border-thickness']
		if 'background-Color' in style and\
			style['background-Color'] != 'transparent':
			bgColor = style['background-Color']
		else: bgColor = None
		if kind=='parent':
			if state==HOVER: ar = arrowhead*2
			else: ar = arrowhead
			grphcs[state].attachNewNode(bevelArrow(frame, bevel, ar, thk, color, borderColor, bgColor))
		elif kind in ('horizontal', 'titleBar', 'close'):
			grphcs[state].attachNewNode(rectangle(frame, thk, color, borderColor, bgColor))
		elif kind=='checkBox':
			grphcs[state].attachNewNode(checkBox(frame, bevel, thk, color, borderColor, bgColor))
			cb = grphcs[state].attachNewNode(checkedBox(frame, bevel, thk, color, borderColor, bgColor))
			cb.hide()
		elif kind=='radioBTN':
			grphcs[state].attachNewNode(radioBTN(frame, bevel, thk, color, borderColor, bgColor))
			cb = grphcs[state].attachNewNode(checkedRadioBTN(frame, bevel, thk, color, borderColor, bgColor))
			cb.hide()
		else:
			grphcs[state].attachNewNode(bevelBG(frame, bevel, thk, borderColor, bgColor))
	return grphcs
예제 #41
0
class Viewer(ShowBase, object):
    """ Viewer for SSOs."""
    def __init__(self):
        ShowBase.__init__(self)
        resize_window = ConfigVariableBool('viewer-resize-window', '#t')
        if resize_window.getValue():
            self.win_size = (800, 800)
        # Black background
        self.win.setClearColor((0.0, 0.0, 0.0, 1.0))
        # Set up lights.
        self.lights = NodePath("lights")
        # Spotlight. Casts shadows.
        slight = Spotlight("slight")
        slight.setScene(self.render)
        slight.setShadowCaster(True, 2**11, 2**11)
        # Set shadow mask, so we can exclude objects from casting shadows
        self.shadow_mask = BitMask32.bit(2)
        slight.setCameraMask(self.shadow_mask)
        slight.setColor((1.2, 1.2, 1.2, 1.))
        slight.getLens().setFov(45)
        slight.getLens().setNearFar(1, 100)
        slnp = self.lights.attachNewNode(slight)
        slnp.setPos((6, 8, 20))
        slnp.lookAt(0, 0, 0)
        self.render.setLight(slnp)
        # Ambient light.
        alight = AmbientLight("alight")
        a = 0.75
        alight.setColor((a, a, a, 1.0))
        #alight.setColor((0.8, 0.8, 0.8, 1.0))
        alnp = self.lights.attachNewNode(alight)
        self.render.setLight(alnp)
        self.lights.reparentTo(self.render)
        # Set auto shading for shadows
        use_shaders = ConfigVariableBool('viewer-use-shaders', '#t')
        if use_shaders.getValue():
            self.render.setShaderAuto()
        # Set antialiasing on
        self.render.setAntialias(AntialiasAttrib.MAuto)
        # Camera
        self.camera_rot = self.render.attachNewNode("camera_rot")
        self.cameras = self.camera_rot.attachNewNode("cameras")
        self.cameras.setPos(14, 32, 9.)
        self.look_at = self.render.attachNewNode("look_at")
        self.look_at.setPos(Point3(2, 0, 1))
        self.cameras.lookAt(self.look_at)
        self.camera.reparentTo(self.cameras)
        # Adjust the camera's lens
        lens = PerspectiveLens()
        self.camLens = lens
        self.camLens.setNearFar(0.01, 1000.0)
        setlens = ConfigVariableBool('viewer-set-cam-lens', '#t')
        if setlens:
            self.cam.node().setLens(self.camLens)
        #
        # Initialize / set variables
        self.sso = None
        self.ssos = []
        self.cache = None
        self.scene = SSO("scene")
        self.scene.reparentTo(self.render)
        # Key callbacks.
        self.accept("shift-control-escape", self.exit)
        self.accept("escape", self.exit)
        self.accept("0", self.reset_sso)
        self.accept("arrow_left", self.prev)
        self.accept("arrow_right", self.next)
        self.accept("page_down", self.prev, [100])
        self.accept("page_up", self.next, [100])
        self.accept("f1", self.toggle_debug)
        self.accept("o", self.physics_once, extraArgs=[1. / 10])
        self.accept("i", self.physics_once, extraArgs=[1. / 10000])
        # Remove existing keyboard tasks.
        self.mandatory_events = ("window-event", "async_loader_0",
                                 "render-texture-targets-changed",
                                 "shift-control-escape")
        # Task list: name: (key, args)
        events = {
            "physics": ("p", ),
            "repel": ("t", ),
            "bump": ("f", ),
            "rotate": ("r", 20),
            "rotate90": ("h", ),
            "ss_task": ("s", ),
            "ssa_task": ("w", ),
            "bp": ("b", )
        }
        # Add events
        for key, val in events.iteritems():
            call = [key] + list(val[1:])
            self.accept(val[0], self.toggle_task, call)
        # These are the key events that we will never ignore
        self.permanent_events = self.getAllAccepting()
        # These are the key events that we will never ignore
        self.permanent_tasks = [
            task.getName() for task in self.taskMgr.getAllTasks()
        ]
        self.start_time = -1
        self.old_elapsed = 0

    @property
    def win_size(self):
        """ Returns window size."""
        props = WindowProperties(self.win.getProperties())
        return props.getXSize(), props.getYSize()

    @win_size.setter
    def win_size(self, wh):
        """ Sets window size."""
        props = WindowProperties(self.win.getProperties())
        props.setSize(*wh)
        self.size = wh
        self.win.requestProperties(props)

    def toggle_fullscreen(self):
        """ Toggles fullscreen mode."""
        props = WindowProperties(self.win.getProperties())
        if props.getFullscreen():
            props.setSize(*self.size)
            props.setFullscreen(False)
        else:
            w = self.pipe.getDisplayWidth()
            h = self.pipe.getDisplayHeight()
            props.setSize(w, h)
            props.setFullscreen(True)
        self.win.requestProperties(props)

    def _get_screen_size(self):
        winx = self.win.getXSize()
        winy = self.win.getYSize()
        return winx, winy

    def _convert_coordinate(self, P0):
        """ Convert 3 coordinates to 2d projection, and 2d coordinates
        to 3d extrusion."""
        P0 = array(P0)
        proj_mat = get_projection_mat(self.cam)
        if P0.size == 2:
            # 2d to 3d.
            line = extrude(P0, proj_mat)
            normal = array((0., 0., 1.))
            P = plane_intersection(line, array(self.origin), normal)
        else:
            # 3d to 2d.
            P = project(P0, proj_mat)
        return P

    def _get_screen_mouse_location(self):
        """ Gets mouse location in screen coordinates."""
        md = self.win.getPointer(0)
        s2d = array((md.getX(), md.getY()))
        return s2d

    def _set_screen_mouse_location(self, s2d):
        """ Sets mouse location in screen coordinates."""
        self.win.movePointer(0, *s2d.astype("i"))

    def _get_cursor_location(self):
        """ Return cursor's 2D or 3D location."""
        # Mouse's screen coordinates
        x = self.mouseWatcherNode.getMouseX()
        y = self.mouseWatcherNode.getMouseY()
        return self._convert_coordinate((x, y))

    def _set_cursor_location(self, p2d):
        """ Sets cursor location in window coords [-1, 1]."""
        s2d = ((p2d * array(
            (1, -1)) + 1.) / 2. * array(self._get_screen_size()))
        self._set_screen_mouse_location(s2d)

    def _set_cursor_hidden(self, b):
        """ Toggle cursor."""
        props = WindowProperties()
        props.setCursorHidden(b)
        self.win.requestProperties(props)

    def draw_cursor2d(self, task):
        """ Draw cursor indicator."""
        if getattr(self, "cursor", None) and self.mouseWatcherNode.hasMouse():
            res = self._get_screen_size()
            ar = float(res[0]) / res[1]
            mx = self.mouseWatcherNode.getMouseX()
            my = self.mouseWatcherNode.getMouseY()
            self.cursor.setPos(mx * ar, 0, my)
        return task.cont

    # def draw_cursor2d(self, task):
    #     """ Draw cursor indicator."""
    #     if getattr(self, "cursor", None) and self.mouseWatcherNode.hasMouse():
    #         mx = self.mouseWatcherNode.getMouseX()
    #         my = self.mouseWatcherNode.getMouseY()
    #         p3d = self._convert_coordinate((mx, my))
    #         p2d = self._convert_coordinate(p3d)[0].squeeze()
    #         res = self._get_screen_size()
    #         ar = float(res[0]) / res[1]
    #         x = p2d[0] * ar
    #         y = p2d[1]
    #         self.cursor.setPos(x, 0., y)
    #     return task.cont

    def init_physics(self, bbase):
        """ Initialize the physics resources."""
        self.bbase = bbase
        self.debug_np = self.render.attachNewNode(self.bbase.setup_debug())

    def init_ssos(self, ssos):
        """ Initialize the ssos."""
        GSO.loader = Loader  # self.graphicsEngine.getDefaultLoader()
        # Put all the input ssos into one list.
        self.ssos = []
        for sso in ssos:
            if not isinstance(sso, NodePath):
                raise TypeError("Must be NodePath: %s (%s)" % (sso, type(sso)))
            # Set up the node and its descendants.
            sso.init_tree(tags=("model", ))
            self.ssos.append(sso)
        # Number of ssos.
        self.n_ssos = len(self.ssos)

    def init_background(self, bg):
        """ Initialize the background."""
        # Put all the input ssos into one list.
        if not isinstance(bg, NodePath):
            raise TypeError("Must be NodePath: %s (%s)" % (bg, type(bg)))
        GSO.loader = Loader  # self.graphicsEngine.getDefaultLoader()
        bg.init_tree(tags=("model", ))
        self.background = bg
        self.background.reparentTo(self.scene)

    def optimize_camera(self):
        """ Calculate good camera parameters given the current stim."""
        top = self.cameras.getTop()
        p0 = Point3()
        p1 = Point3()
        self.sso.calcTightBounds(p0, p1)
        shape = p1 - p0
        extent = (shape[0], shape[2])
        extent = [max(extent)] * 2
        center = shape / 2. + p0
        # Adjust camera's x-position.
        self.cameras.setX(top, center[0])
        self.cameras.setZ(top, p1[2])
        # Compute where camera will point.
        # look_at = Point3(center[0], self.look_at.getY(), self.look_at.getZ())
        # look_at = (center[0], center[1], self.look_at.getZ())
        look_at = center
        origin = Point3(center[0], center[1], p1[2])
        displacement = self.cameras.getPos(top) - origin
        distance = displacement.length()
        fov = self.cam.node().getLens().getFov()
        target_ratio = 0.65
        dx = extent[0] / 2. / target_ratio / tan(radians(fov[0]) / 2.)
        dz = extent[1] / 2. / target_ratio / tan(radians(fov[1]) / 2.)
        dr = max(dx, dz) / distance
        pos = origin + displacement * dr
        self.cameras.setPos(top, pos)
        #BP()
        # Point camera toward stim.
        self.look_at.setPos(top, look_at)
        self.cameras.lookAt(self.look_at)

    def _load(self, model):
        """ Wrapper for egg/bam loading."""
        node = NodePath(GSO.loader.loadSync(model))
        return node

    def toggle_task(self, taskname, sort=0):
        """ Toggles taskMgr task 'taskname'."""
        if not self.taskMgr.hasTaskNamed(taskname):
            self.taskMgr.add(getattr(self, taskname), taskname, sort=sort)
            if taskname == "physics":
                self.reset_physics()
        else:
            self.taskMgr.remove(taskname)

    def reset_physics(self):
        """ Resets physics."""
        self.start_time = self.taskMgr.globalClock.getFrameTime()
        self.old_elapsed = 0.

    def physics(self, task):
        """ Task: simulate physics."""
        # Elapsed time.
        dt = self._get_elapsed() - self.old_elapsed
        # Update amount of time simulated so far.
        self.old_elapsed += dt
        # Step the physics dt time.
        size_sub = self.bbase.sim_par["size_sub"]
        n_subs = int(dt / size_sub)
        self.bbase.step(dt, n_subs, size_sub)
        return task.cont

    def repel(self, task):
        """ Task: perform repel."""
        self.bbase.repel()
        return task.done

    def bump(self, task):
        """ Task: perform bump."""
        mag0 = Vec3(0, 0, 1. / self.bbase.sim_par["size"]) * 10.
        pos = Point3(-1, 0, 0)
        nodes = self.background.descendants()
        bodies = [n.node() for n in nodes if n.type_ is BulletRigidBodyNode]
        for body in bodies:
            mag = mag0 * body.getMass()
            print mag
            body.applyForce(mag, pos)
        #BP()
        return task.done

    def physics_once(self, dt):
        """ Step the physics dt."""
        n_subs = 10
        size_sub = dt / n_subs
        self.bbase.step(dt, n_subs, size_sub)
        # self.bbase.attenuate_velocities(self.bbase.get_bodies())

    def bp(self, task):
        """ Task: break."""
        BP()
        return task.done

    def toggle_debug(self):
        """ Shows/hides debug node."""
        if self.debug_np.isHidden():
            self.debug_np.show()
        else:
            self.debug_np.hide()

    def rotate(self, task):
        """ Task: rotate camera."""
        H = (self.camera_rot.getH() + 1) % 360
        self.camera_rot.setH(H)
        return task.cont

    def rotate90(self, task):
        """ Task: rotate in ticks."""
        angs = [15, 105, 195, 285]
        H = int(self.camera_rot.getH())
        if H in angs:
            self.camera_rot.setH(angs[(angs.index(H) + 1) % len(angs)])
        else:
            self.camera_rot.setH(angs[0])
        return task.done

    def ss_task(self, task):
        """ Task: Take a screenshot."""
        self.screenshot()
        return task.done

    def ssa_task(self, task):
        """ Task: Take a screenshot of every sso."""
        self.screenshot(namePrefix=self.sso.getName() + ".jpg",
                        defaultFilename=False)
        if self.n_ssos - 1 == self.ssos.index(self.sso):
            return task.done
        self.next()
        return task.cont

    def _expunge_events(self):
        """ Turn OFF any non-permanent key handlers."""
        events = self.getAllAccepting()
        for event in set(events).difference(self.permanent_events):
            self.ignore(event)

    def _expunge_tasks(self):
        """ Turn OFF any non-permanent tasks floating around."""
        tasknames = [task.getName() for task in self.taskMgr.getAllTasks()]
        for taskname in set(tasknames).difference(self.permanent_tasks):
            self.taskMgr.remove(taskname)

    def reset_sso(self):
        """ Reset to initial scene state."""
        self.goto_sso(self.ssos.index(self.sso))

    def goto_sso(self, i):
        """ Switches to the i-th SSO."""
        print "SSO %d" % i
        # Remove existing tasks and events.
        self._expunge_tasks()
        self._expunge_events()
        if getattr(self, "sso", False):
            # Detach from physical world.
            self.bbase.remove_all()
            # Reset its state to the initial one.
            self.cache.restore()
            # Detach from scene.
            self.sso.detachNode()
        # Set the new sso.
        self.sso = self.ssos[i]
        self.sso.reparentTo(self.scene)
        self.cache = self.scene.store_tree()
        self.attach_physics()
        self.optimize_camera()

    def attach_physics(self):
        # Attach `self.scene` to the physics world.
        self.scene.init_tree(tags=("shape", ))
        bnodes = self.scene.descendants(type_=PSO)
        for bnode in bnodes:
            bnode.setCollideMask(BitMask32.allOn())
            bnode.node().setDeactivationEnabled(False)
        self.bbase.attach(bnodes)

    def remove_physics(self):
        # Remove `self.scene` from the physics world.
        self.bbase.remove(self.scene.descendants(type_=PSO))
        self.scene.destroy_tree(tags=("shape", ))

    def prev(self, steps=1):
        """ Task: Go back one SSO."""
        i = max(0, self.ssos.index(self.sso) - steps)
        self.goto_sso(i)

    def next(self, steps=1):
        """ Task: Go forward one SSO."""
        i = min(self.n_ssos - 1, self.ssos.index(self.sso) + steps)
        self.goto_sso(i)

    def _get_elapsed(self):
        """ Gets the time spent in this phase so far."""
        # Current time.
        current_time = self.taskMgr.globalClock.getFrameTime()
        # Elapsed time in this phase
        elapsed = current_time - self.start_time
        return elapsed

    def run(self):
        # Start with first sso.
        self.goto_sso(0)
        # Call parent's run().
        ShowBase.run(self)

    def exit(self):
        """ Stuff to do before exiting."""
        sys.exit()
class DistributedPartyActivity(DistributedObject.DistributedObject):
    deferFor = 1

    def __init__(self, cr, activityId, activityType, wantLever = False, wantRewardGui = False):
        DistributedObject.DistributedObject.__init__(self, cr)
        self.activityId = activityId
        self.activityName = PartyGlobals.ActivityIds.getString(self.activityId)
        self.activityType = activityType
        self.wantLever = wantLever
        self.wantRewardGui = wantRewardGui
        self.messageGui = None
        self.rewardGui = None
        self.toonIds = []
        self._toonId2ror = {}
        childName = '%s' % self
        childName = childName[childName.rfind('.DistributedParty') + len('.DistributedParty'):childName.rfind('Activity instance')]
        if not hasattr(base, 'partyActivityDict'):
            base.partyActivityDict = {}
        base.partyActivityDict[childName] = self
        self.root = NodePath('root')
        self.rulesDoneEvent = 'rulesDone'
        self.modelCount = 500
        self.cleanupActions = []
        self.usesSmoothing = 0
        self.usesLookAround = 0
        self.difficultyOverride = None
        self.trolleyZoneOverride = None
        self._localToonRequestStatus = None
        return

    def localToonExiting(self):
        self._localToonRequestStatus = PartyGlobals.ActivityRequestStatus.Exiting

    def localToonJoining(self):
        self._localToonRequestStatus = PartyGlobals.ActivityRequestStatus.Joining

    def d_toonJoinRequest(self):
        if self._localToonRequestStatus is None:
            self.localToonJoining()
            self.sendUpdate('toonJoinRequest')
        return

    def d_toonExitRequest(self):
        if self._localToonRequestStatus is None:
            self.localToonExiting()
            self.sendUpdate('toonExitRequest')
        return

    def d_toonExitDemand(self):
        self.localToonExiting()
        self.sendUpdate('toonExitDemand')

    def joinRequestDenied(self, reason):
        self._localToonRequestStatus = None
        return

    def exitRequestDenied(self, reason):
        self._localToonRequestStatus = None
        return

    def handleToonJoined(self, toonId):
        self.notify.error('BASE: handleToonJoined should be overridden %s' % self.activityName)

    def handleToonExited(self, toonId):
        self.notify.error('BASE: handleToonExited should be overridden %s' % self.activityName)

    def handleToonDisabled(self, toonId):
        self.notify.error('BASE: handleToonDisabled should be overridden %s' % self.activityName)

    def setToonsPlaying(self, toonIds):
        exitedToons, joinedToons = self.getToonsPlayingChanges(self.toonIds, toonIds)
        self.setToonIds(toonIds)
        self._processExitedToons(exitedToons)
        self._processJoinedToons(joinedToons)

    def _processExitedToons(self, exitedToons):
        for toonId in exitedToons:
            if toonId != base.localAvatar.doId or toonId == base.localAvatar.doId and self.isLocalToonRequestStatus(PartyGlobals.ActivityRequestStatus.Exiting):
                toon = self.getAvatar(toonId)
                if toon is not None:
                    self.ignore(toon.uniqueName('disable'))
                self.handleToonExited(toonId)
                if toonId == base.localAvatar.doId:
                    self._localToonRequestStatus = None
                if toonId in self._toonId2ror:
                    self.cr.relatedObjectMgr.abortRequest(self._toonId2ror[toonId])
                    del self._toonId2ror[toonId]

        return

    def _processJoinedToons(self, joinedToons):
        for toonId in joinedToons:
            if toonId != base.localAvatar.doId or toonId == base.localAvatar.doId and self.isLocalToonRequestStatus(PartyGlobals.ActivityRequestStatus.Joining):
                if toonId not in self._toonId2ror:
                    request = self.cr.relatedObjectMgr.requestObjects([toonId], allCallback=self._handlePlayerPresent)
                    if toonId in self._toonId2ror:
                        del self._toonId2ror[toonId]
                    else:
                        self._toonId2ror[toonId] = request

    def _handlePlayerPresent(self, toons):
        toon = toons[0]
        toonId = toon.doId
        if toonId in self._toonId2ror:
            del self._toonId2ror[toonId]
        else:
            self._toonId2ror[toonId] = None
        self._enableHandleToonDisabled(toonId)
        self.handleToonJoined(toonId)
        if toonId == base.localAvatar.doId:
            self._localToonRequestStatus = None
        return

    def _enableHandleToonDisabled(self, toonId):
        toon = self.getAvatar(toonId)
        if toon is not None:
            self.acceptOnce(toon.uniqueName('disable'), self.handleToonDisabled, [toonId])
        else:
            self.notify.warning('BASE: unable to get handle to toon with toonId:%d. Hook for handleToonDisabled not set.' % toonId)
        return

    def isLocalToonRequestStatus(self, requestStatus):
        return self._localToonRequestStatus == requestStatus

    def setToonIds(self, toonIds):
        self.toonIds = toonIds

    def getToonsPlayingChanges(self, oldToonIds, newToonIds):
        oldToons = set(oldToonIds)
        newToons = set(newToonIds)
        exitedToons = oldToons.difference(newToons)
        joinedToons = newToons.difference(oldToons)
        return (list(exitedToons), list(joinedToons))

    def setUsesSmoothing(self):
        self.usesSmoothing = True

    def setUsesLookAround(self):
        self.usesLookAround = True

    def getInstructions(self):
        return TTLocalizer.DefaultPartyActivityInstructions

    def getParentNodePath(self):
        if hasattr(base.cr.playGame, 'hood') and base.cr.playGame.hood and hasattr(base.cr.playGame.hood, 'loader') and base.cr.playGame.hood.loader and hasattr(base.cr.playGame.hood.loader, 'geom') and base.cr.playGame.hood.loader.geom:
            return base.cr.playGame.hood.loader.geom
        else:
            self.notify.warning('Hood or loader not created, defaulting to render')
            return render

    def __createRandomNumGen(self):
        self.notify.debug('BASE: self.doId=0x%08X' % self.doId)
        self.randomNumGen = RandomNumGen.RandomNumGen(self.doId)

        def destroy(self = self):
            self.notify.debug('BASE: destroying random num gen')
            del self.randomNumGen

        self.cleanupActions.append(destroy)

    def generate(self):
        DistributedObject.DistributedObject.generate(self)
        self.notify.debug('BASE: generate, %s' % self.getTitle())
        self.__createRandomNumGen()

    def announceGenerate(self):
        DistributedObject.DistributedObject.announceGenerate(self)
        self.notify.debug('BASE: announceGenerate %s' % self.activityName)
        self.root.setName(self.activityName + 'Root')
        centeredX, centeredY = getCenterPosFromGridSize(self.x, self.y, PartyGlobals.ActivityInformationDict[self.activityId]['gridsize'])
        self.root.setPos(centeredX, centeredY, 0.0)
        self.root.setH(self.h)
        self.normalExit = True
        if self.wantLever:
            self.leverTriggerEvent = self.uniqueName('leverTriggerEvent')
        self.load()

        def cleanup(self = self):
            self.notify.debug('BASE: cleanup: normalExit=%s' % self.normalExit)
            base.cr.renderFrame()
            if self.normalExit:
                self.sendUpdate('toonExitRequest')

        self.cleanupActions.append(cleanup)

    def disable(self):
        self.notify.debug('BASE: disable')
        DistributedObject.DistributedObject.disable(self)
        rorToonIds = self._toonId2ror.keys()
        for toonId in rorToonIds:
            self.cr.relatedObjectMgr.abortRequest(self._toonId2ror[toonId])
            del self._toonId2ror[toonId]

        self.ignore(self.messageDoneEvent)
        if self.messageGui is not None and not self.messageGui.isEmpty():
            self.messageGui.cleanup()
            self.messageGui = None
        return

    def delete(self):
        self.notify.debug('BASE: delete')
        self.unload()
        self.ignoreAll()
        DistributedObject.DistributedObject.delete(self)

    def load(self):
        self.notify.debug('BASE: load')
        self.loadSign()
        if self.wantLever:
            self.loadLever()
        if self.wantRewardGui:
            self.showRewardDoneEvent = self.uniqueName('showRewardDoneEvent')
            self.rewardGui = JellybeanRewardGui(self.showRewardDoneEvent)
        self.messageDoneEvent = self.uniqueName('messageDoneEvent')
        self.root.reparentTo(self.getParentNodePath())
        self._enableCollisions()

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

    def loadLever(self):
        self.lever = self.root.attachNewNode('%sLever' % self.activityName)
        self.leverModel = self.party.defaultLeverModel.copyTo(self.lever)
        self.controlColumn = NodePath('cc')
        column = self.leverModel.find('**/column')
        column.getChildren().reparentTo(self.controlColumn)
        self.controlColumn.reparentTo(column)
        self.stickHinge = self.controlColumn.attachNewNode('stickHinge')
        self.stick = self.party.defaultStickModel.copyTo(self.stickHinge)
        self.stickHinge.setHpr(0.0, 90.0, 0.0)
        self.stick.setHpr(0, -90.0, 0)
        self.stick.flattenLight()
        self.bottom = self.leverModel.find('**/bottom')
        self.bottom.wrtReparentTo(self.controlColumn)
        self.bottomPos = self.bottom.getPos()
        cs = CollisionSphere(0.0, 1.35, 2.0, 1.0)
        cs.setTangible(False)
        cn = CollisionNode(self.leverTriggerEvent)
        cn.addSolid(cs)
        cn.setIntoCollideMask(OTPGlobals.WallBitmask)
        self.leverTrigger = self.root.attachNewNode(cn)
        self.leverTrigger.reparentTo(self.lever)
        self.leverTrigger.stash()
        cs = CollisionTube(0.0, 2.7, 0.0, 0.0, 2.7, 3.0, 1.2)
        cn = CollisionNode('levertube')
        cn.addSolid(cs)
        cn.setIntoCollideMask(OTPGlobals.WallBitmask)
        self.leverTube = self.leverModel.attachNewNode(cn)
        host = base.cr.doId2do.get(self.party.partyInfo.hostId)
        if host is None:
            self.notify.debug('%s loadLever : Host has left the game before lever could be created.' % self.activityName)
            return
        scale = host.getGeomNode().getChild(0).getSz(render)
        self.leverModel.setScale(scale)
        self.controlColumn.setPos(0, 0, 0)
        host.setPosHpr(self.lever, 0, 0, 0, 0, 0, 0)
        host.pose('leverNeutral', 0)
        host.update()
        pos = host.rightHand.getPos(self.controlColumn)
        self.controlColumn.setPos(pos[0], pos[1], pos[2] - 1)
        self.bottom.setZ(host, 0.0)
        self.bottom.setPos(self.bottomPos[0], self.bottomPos[1], self.bottom.getZ())
        lookAtPoint = Point3(0.3, 0, 0.1)
        lookAtUp = Vec3(0, -1, 0)
        self.stickHinge.lookAt(host.rightHand, lookAtPoint, lookAtUp)
        host.play('walk')
        host.update()
        return

    def unloadLever(self):
        self.lever.removeNode()
        self.leverModel.removeNode()
        self.controlColumn.removeNode()
        self.stickHinge.removeNode()
        self.stick.removeNode()
        self.bottom.removeNode()
        self.leverTrigger.removeNode()
        self.leverTube.removeNode()
        del self.bottomPos
        del self.lever
        del self.leverModel
        del self.controlColumn
        del self.stickHinge
        del self.stick
        del self.bottom
        del self.leverTrigger
        del self.leverTube

    def _enableCollisions(self):
        if self.wantLever:
            self.leverTrigger.unstash()
            self.accept('enter%s' % self.leverTriggerEvent, self._leverPulled)

    def _disableCollisions(self):
        if self.wantLever:
            self.leverTrigger.stash()
            self.ignore('enter%s' % self.leverTriggerEvent)

    def _leverPulled(self, collEntry):
        self.notify.debug('_leverPulled : Someone pulled the lever!!! ')
        if self.activityType == PartyGlobals.ActivityTypes.HostInitiated and base.localAvatar.doId != self.party.partyInfo.hostId:
            return False
        return True

    def getToonPullingLeverInterval(self, toon):
        walkTime = 0.2
        reach = ActorInterval(toon, 'leverReach', playRate=2.0)
        pull = ActorInterval(toon, 'leverPull', startFrame=6)
        origPos = toon.getPos(render)
        origHpr = toon.getHpr(render)
        newPos = self.lever.getPos(render)
        newHpr = self.lever.getHpr(render)
        origHpr.setX(PythonUtil.fitSrcAngle2Dest(origHpr[0], newHpr[0]))
        toon.setPosHpr(origPos, origHpr)
        reachAndPull = Sequence(ActorInterval(toon, 'walk', loop=True, duration=walkTime - reach.getDuration()), reach, pull)
        leverSeq = Sequence(Wait(walkTime + reach.getDuration() - 0.1), self.stick.hprInterval(0.55, Point3(0.0, 25.0, 0.0), Point3(0.0, 0.0, 0.0)), Wait(0.3), self.stick.hprInterval(0.4, Point3(0.0, 0.0, 0.0), Point3(0.0, 25.0, 0.0)))
        returnSeq = Sequence(Parallel(toon.posInterval(walkTime, newPos, origPos), toon.hprInterval(walkTime, newHpr, origHpr), leverSeq, reachAndPull))
        return returnSeq

    def showMessage(self, message, endState = 'walk'):
        base.cr.playGame.getPlace().fsm.request('activity')
        self.acceptOnce(self.messageDoneEvent, self.__handleMessageDone)
        self.messageGui = TTDialog.TTGlobalDialog(doneEvent=self.messageDoneEvent, message=message, style=TTDialog.Acknowledge)
        self.messageGui.endState = endState

    def __handleMessageDone(self):
        self.ignore(self.messageDoneEvent)
        if hasattr(base.cr.playGame.getPlace(), 'fsm'):
            if self.messageGui and hasattr(self.messageGui, 'endState'):
                self.notify.info('__handleMessageDone (endState=%s)' % self.messageGui.endState)
                base.cr.playGame.getPlace().fsm.request(self.messageGui.endState)
            else:
                self.notify.warning("messageGui has no endState, defaulting to 'walk'")
                base.cr.playGame.getPlace().fsm.request('walk')
        if self.messageGui is not None and not self.messageGui.isEmpty():
            self.messageGui.cleanup()
            self.messageGui = None
        return

    def showJellybeanReward(self, earnedAmount, jarAmount, message):
        if not self.isLocalToonInActivity() or base.localAvatar.doId in self.getToonIdsAsList():
            messenger.send('DistributedPartyActivity-showJellybeanReward')
            base.cr.playGame.getPlace().fsm.request('activity')
            self.acceptOnce(self.showRewardDoneEvent, self.__handleJellybeanRewardDone)
            self.rewardGui.showReward(earnedAmount, jarAmount, message)

    def __handleJellybeanRewardDone(self):
        self.ignore(self.showRewardDoneEvent)
        self.handleRewardDone()

    def handleRewardDone(self):
        if base.cr.playGame.getPlace() and hasattr(base.cr.playGame.getPlace(), 'fsm'):
            base.cr.playGame.getPlace().fsm.request('walk')

    def setSignNote(self, note):
        self.noteText.node().setText(note)
        if len(note.strip()) > 0:
            self.signFlat.stash()
            self.signFlatWithNote.unstash()
            self.signTextLocator.unstash()
        else:
            self.signFlat.unstash()
            self.signFlatWithNote.stash()
            self.signTextLocator.stash()

    def unload(self):
        self.notify.debug('BASE: unload')
        self.finishRules()
        self._disableCollisions()
        self.signModel.removeNode()
        del self.signModel
        self.sign.removeNode()
        del self.sign
        self.ignoreAll()
        if self.wantLever:
            self.unloadLever()
        self.root.removeNode()
        del self.root
        del self.activityId
        del self.activityName
        del self.activityType
        del self.wantLever
        del self.messageGui
        if self.rewardGui is not None:
            self.rewardGui.destroy()
        del self.rewardGui
        if hasattr(self, 'toonIds'):
            del self.toonIds
        del self.rulesDoneEvent
        del self.modelCount
        del self.cleanupActions
        del self.usesSmoothing
        del self.usesLookAround
        del self.difficultyOverride
        del self.trolleyZoneOverride
        if hasattr(base, 'partyActivityDict'):
            del base.partyActivityDict
        return

    def setPartyDoId(self, partyDoId):
        self.party = base.cr.doId2do[partyDoId]

    def setX(self, x):
        self.x = x

    def setY(self, y):
        self.y = y

    def setH(self, h):
        self.h = h

    def setState(self, newState, timestamp):
        if newState == 'Active':
            self.activityStartTime = globalClockDelta.networkToLocalTime(timestamp)

    def turnOffSmoothingOnGuests(self):
        for toonId in self.toonIds:
            avatar = self.getAvatar(toonId)
            if avatar:
                if not self.usesSmoothing:
                    avatar.stopSmooth()
                if not self.usesLookAround:
                    avatar.stopLookAround()

    def getAvatar(self, toonId):
        if self.cr.doId2do.has_key(toonId):
            return self.cr.doId2do[toonId]
        else:
            self.notify.warning('BASE: getAvatar: No avatar in doId2do with id: ' + str(toonId))
            return None
        return None

    def getAvatarName(self, toonId):
        avatar = self.getAvatar(toonId)
        if avatar:
            return avatar.getName()
        else:
            return 'Unknown'

    def isLocalToonInActivity(self):
        result = False
        place = base.cr.playGame.getPlace()
        if place and place.__class__.__name__ == 'Party' and hasattr(place, 'fsm') and place.fsm:
            result = place.fsm.getCurrentState().getName() == 'activity'
        return result

    def getToonIdsAsList(self):
        return self.toonIds

    def startRules(self, timeout = PartyGlobals.DefaultRulesTimeout):
        self.notify.debug('BASE: startRules')
        self.accept(self.rulesDoneEvent, self.handleRulesDone)
        self.rulesPanel = MinigameRulesPanel('PartyRulesPanel', self.getTitle(), self.getInstructions(), self.rulesDoneEvent, timeout)
        base.setCellsAvailable(base.bottomCells + [base.leftCells[0], base.rightCells[1]], False)
        self.rulesPanel.load()
        self.rulesPanel.enter()

    def finishRules(self):
        self.notify.debug('BASE: finishRules')
        self.ignore(self.rulesDoneEvent)
        if hasattr(self, 'rulesPanel'):
            self.rulesPanel.exit()
            self.rulesPanel.unload()
            del self.rulesPanel
            base.setCellsAvailable(base.bottomCells + [base.leftCells[0], base.rightCells[1]], True)

    def handleRulesDone(self):
        self.notify.error('BASE: handleRulesDone should be overridden')

    def getTitle(self):
        return TTLocalizer.PartyActivityNameDict[self.activityId]['generic']

    def local2ActivityTime(self, timestamp):
        return timestamp - self.activityStartTime

    def activity2LocalTime(self, timestamp):
        return timestamp + self.activityStartTime

    def getCurrentActivityTime(self):
        return self.local2ActivityTime(globalClock.getFrameTime())

    def disableEmotes(self):
        Emote.globalEmote.disableAll(base.localAvatar)

    def enableEmotes(self):
        Emote.globalEmote.releaseAll(base.localAvatar)
예제 #43
0
class DistributedLawnDecor(DistributedNode.DistributedNode, NodePath, ShadowCaster.ShadowCaster):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLawnDecor')

    def __init__(self, cr):
        DistributedNode.DistributedNode.__init__(self, cr)
        NodePath.__init__(self, 'decor')
        ShadowCaster.ShadowCaster.__init__(self, False)
        self.plantPath = NodePath('plantPath')
        self.plantPath.reparentTo(self)
        self.defaultModel = 'phase_9/models/cogHQ/woodCrateB'
        self.messageName = None
        self.model = None
        self.colSphereNode = None
        self.rotateNode = None
        self.collSphereOffset = 0.0
        self.collSphereRadius = 1.0
        self.stickUp = 0.0
        self.movieNode = None
        self.shadowJoint = None
        self.shadowScale = 1
        self.expectingReplacement = 0
        self.movie = None
        return

    def setHeading(self, h):
        self.notify.debug('setting h')
        DistributedNode.DistributedNode.setH(self, h)

    def generateInit(self):
        self.notify.debug('generateInit')
        DistributedNode.DistributedNode.generateInit(self)

    def generate(self):
        self.notify.debug('generate')
        self.reparentTo(render)
        DistributedNode.DistributedNode.generate(self)

    def announceGenerate(self):
        self.notify.debug('announceGenerate')
        DistributedNode.DistributedNode.announceGenerate(self)
        self.doModelSetup()
        self.loadModel()
        self.setupShadow()
        self.makeMovieNode()
        self.stick2Ground()
        self.setupCollision()

    def doModelSetup(self):
        pass

    def disable(self):
        self.notify.debug('disable')
        self.finishMovies()
        self.handleExitPlot()
        self.ignoreAll()
        DistributedNode.DistributedNode.disable(self)
        if hasattr(self, 'nodePath'):
            self.nodePath.detachNode()

    def delete(self):
        self.notify.debug('delete')
        ShadowCaster.ShadowCaster.delete(self)
        self.unloadModel()
        DistributedNode.DistributedNode.delete(self)

    def loadModel(self):
        if not self.rotateNode:
            self.rotateNode = self.plantPath.attachNewNode('rotate')
        self.model = None
        if __dev__:
            self.model = loader.loadModel(self.defaultModel)
            self.model.setScale(0.4, 0.4, 0.1)
            self.model.reparentTo(self.rotateNode)
        return

    def setupShadow(self):
        self.shadowJoint = self.rotateNode.attachNewNode('shadow')
        self.initializeDropShadow(False)
        self.shadowJoint.setScale(self.shadowScale)
        self.setActiveShadow()

    def makeMovieNode(self):
        self.movieNode = self.rotateNode.attachNewNode('moviePos')
        self.movieNode.setPos(0, -3, 0)

    def setupCollision(self):
        self.messageName = self.uniqueName('enterplotSphere')
        self.messageStartName = self.uniqueName('plotSphere')
        self.exitMessageName = self.uniqueName('exitplotSphere')
        if self.collSphereOffset <= 0.1:
            colSphere = CollisionSphere(0, 0, 0, self.collSphereRadius)
        else:
            colSphere = CollisionTube(0, -self.collSphereOffset, 0, 0, self.collSphereOffset, 0, self.collSphereRadius)
        colSphere.setTangible(0)
        colNode = CollisionNode(self.messageStartName)
        colNode.addSolid(colSphere)
        colSphereNode = self.attachNewNode(colNode)
        self.colSphereNode = colSphereNode
        self.accept(self.messageName, self.handleEnterPlot)
        self.accept(self.exitMessageName, self.handleExitPlot)

    def handleEnterPlot(self, optional = None):
        self.notify.debug('handleEnterPlot %d' % self.doId)
        self.sendUpdate('plotEntered', [])

    def handleExitPlot(self, optional = None):
        if base.localAvatar.inGardenAction == self:
            base.localAvatar.handleEndPlantInteraction(self, replacement=self.expectingReplacement)

    def handleWatering(self):
        self.handleExitPlot()
        base.localAvatar.removeShovelRelatedDoId(self.doId)

    def unloadModel(self):
        if self.model:
            self.model.removeNode()
            del self.model
            self.model = None
        if hasattr(self, 'nodePath') and self.nodePath:
            self.nodePath.removeNode()
            self.nodePath = None
        taskMgr.remove(self.uniqueName('adjust tree'))
        return

    def setPos(self, x, y, z):
        DistributedNode.DistributedNode.setPos(self, x, y, z)
        self.stick2Ground()

    def setPosition(self, x, y, z):
        DistributedNode.DistributedNode.setPos(self, x, y, z)
        self.stick2Ground()

    def stick2Ground(self, taskfooler = 0):
        if self.isEmpty():
            return Task.done
        testPath = NodePath('testPath')
        testPath.reparentTo(render)
        cRay = CollisionRay(0.0, 0.0, 40000.0, 0.0, 0.0, -1.0)
        cRayNode = CollisionNode(self.uniqueName('estate-FloorRay'))
        cRayNode.addSolid(cRay)
        cRayNode.setFromCollideMask(OTPGlobals.FloorBitmask)
        cRayNode.setIntoCollideMask(BitMask32.allOff())
        cRayNodePath = testPath.attachNewNode(cRayNode)
        queue = CollisionHandlerQueue()
        picker = CollisionTraverser()
        picker.addCollider(cRayNodePath, queue)
        if self.movieNode:
            testPath.setPos(self.movieNode.getX(render), self.movieNode.getY(render), 0)
            picker.traverse(render)
            if queue.getNumEntries() > 0:
                queue.sortEntries()
                for index in xrange(queue.getNumEntries()):
                    entry = queue.getEntry(index)
                    if recurseParent(entry.getIntoNode(), 'terrain_DNARoot'):
                        self.movieNode.setZ(entry.getSurfacePoint(self)[2])

        testPath.setPos(self.getX(), self.getY(), 0)
        picker.traverse(render)
        if queue.getNumEntries() > 0:
            queue.sortEntries()
            for index in xrange(queue.getNumEntries()):
                entry = queue.getEntry(index)
                if recurseParent(entry.getIntoNode(), 'terrain_DNARoot'):
                    self.setZ(entry.getSurfacePoint(render)[2] + self.stickUp + 0.1)
                    self.stickParts()
                    return Task.done

        taskMgr.doMethodLater(1.0, self.stick2Ground, uniqueName('groundsticker'))
        return Task.done

    def stickParts(self):
        pass

    def setPlot(self, plot):
        self.plot = plot

    def setH(self, h):
        DistributedNode.DistributedNode.setH(self, h)

    def getPlot(self):
        return self.plot

    def setOwnerIndex(self, index):
        self.ownerIndex = index

    def getOwnerIndex(self):
        return self.ownerIndex

    def getOwnerId(self):
        retval = 0
        estate = base.cr.doFind('DistributedEstate')
        if estate and hasattr(estate, 'idList') and estate.idList:
            if self.ownerIndex < len(estate.idList):
                retval = estate.idList[self.ownerIndex]
        return retval

    def canBePicked(self):
        retval = True
        self.notify.debug('base.localAvatar.doId : %s' % base.localAvatar.doId)
        self.notify.debug('self.getOwnerId : %s ' % self.getOwnerId())
        self.notify.debug("statue's DoId : %s " % self.doId)
        if not hasattr(base, 'localAvatar') or not base.localAvatar.doId == self.getOwnerId():
            retval = False
        return retval

    def allowedToPick(self):
        return True

    def unlockPick(self):
        return True

    def handleRemove(self):
        if not self.canBePicked():
            self.notify.debug("I don't own this item, just returning")
            return
        base.localAvatar.hideShovelButton()
        base.localAvatar.hideWateringCanButton()
        self.startInteraction()
        self.sendUpdate('removeItem', [])

    def generateToonMoveTrack(self, toon):
        node = NodePath('tempNode')
        displacement = Vec3(toon.getPos(render) - self.getPos(render))
        displacement.setZ(0)
        displacement.normalize()
        movieDistance = self.movieNode.getDistance(self.rotateNode)
        displacement *= movieDistance
        node.reparentTo(render)
        node.setPos(displacement + self.getPos(render))
        node.lookAt(self)
        heading = PythonUtil.fitDestAngle2Src(toon.getH(render), node.getH(render))
        hpr = toon.getHpr(render)
        hpr.setX(heading)
        finalX = node.getX(render)
        finalY = node.getY(render)
        finalZ = node.getZ(render)
        node.removeNode()
        toonTrack = Sequence(Parallel(ActorInterval(toon, 'walk', loop=True, duration=1), Parallel(LerpPosInterval(toon, 1.0, Point3(finalX, finalY, toon.getZ(render)), fluid=True, bakeInStart=False)), LerpHprInterval(toon, 1.0, hpr=hpr)), Func(toon.loop, 'neutral'))
        return toonTrack

    def unprint(self, string):
        print string

    def startInteraction(self):
        place = base.cr.playGame.getPlace()
        if place:
            place.detectedGardenPlotUse()
            base.localAvatar.setInGardenAction(self)

    def finishInteraction(self):
        if hasattr(base.cr.playGame.getPlace(), 'detectedGardenPlotDone'):
            base.cr.playGame.getPlace().detectedGardenPlotDone()
            self.notify.debug('done interaction')
        else:
            self.notify.warning('base.cr.playGame.getPlace() does not have detectedGardenPlotDone')
        if hasattr(base, 'localAvatar'):
            base.localAvatar.handleEndPlantInteraction(self)

    def startCamIval(self, avId):
        track = Sequence()
        if avId == localAvatar.doId:
            track = Sequence(Func(base.localAvatar.disableSmartCameraViews), Func(base.localAvatar.setCameraPosForPetInteraction))
        return track

    def stopCamIval(self, avId):
        track = Sequence()
        if avId == localAvatar.doId:
            track = Sequence(Func(base.localAvatar.unsetCameraPosForPetInteraction), Wait(0.8), Func(base.localAvatar.enableSmartCameraViews))
        return track

    def canBeWatered(self):
        return 0

    def getShovelAction(self):
        return None

    def getShovelCommand(self):
        return None

    def canBePlanted(self):
        return 0

    def movieDone(self):
        self.sendUpdate('movieDone', [])

    def setMovie(self, mode, avId):
        if mode == GardenGlobals.MOVIE_FINISHPLANTING:
            self.doFinishPlantingTrack(avId)
        elif mode == GardenGlobals.MOVIE_REMOVE:
            self.doDigupTrack(avId)

    def finishMovies(self):
        if self.movie:
            self.movie.finish()
            self.movie = None
        return

    def doDigupTrack(self, avId):
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.finishMovies()
        self.model.setTransparency(1)
        self.model.setAlphaScale(1)
        shovel = toon.attachShovel()
        shovel.hide()
        moveTrack = self.generateToonMoveTrack(toon)
        digupTrack = self.generateDigupTrack(toon)
        self.movie = Sequence(self.startCamIval(avId), moveTrack, Func(shovel.show), digupTrack)
        if avId == localAvatar.doId:
            self.expectingReplacement = 1
            self.movie.append(Func(self.movieDone))
        self.movie.start()

    def generateDigupTrack(self, toon):
        sound = loader.loadSfx('phase_5.5/audio/sfx/burrow.ogg')
        sound.setPlayRate(0.5)
        pos = self.model.getPos()
        pos.setZ(pos[2] - 1)
        track = Parallel()
        track.append(Sequence(ActorInterval(toon, 'start-dig'), Parallel(ActorInterval(toon, 'loop-dig', loop=1, duration=5.13), Sequence(Wait(0.25), SoundInterval(sound, node=toon, duration=0.55), Wait(0.8), SoundInterval(sound, node=toon, duration=0.55), Wait(1.35), SoundInterval(sound, node=toon, duration=0.55))), ActorInterval(toon, 'start-dig', playRate=-1), LerpFunc(self.model.setAlphaScale, fromData=1, toData=0, duration=1), Func(toon.loop, 'neutral'), Func(toon.detachShovel)))
        return track

    def doFinishPlantingTrack(self, avId):
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.finishMovies()
        self.movie = Sequence()
        if avId == localAvatar.doId:
            self.startInteraction()
        if self.model:
            self.model.setTransparency(1)
            self.model.setAlphaScale(0)
            self.movie.append(LerpFunc(self.model.setAlphaScale, fromData=0, toData=1, duration=3))
        self.movie.append(self.stopCamIval(avId))
        self.movie.append(Func(toon.detachShovel))
        self.movie.append(Func(toon.loop, 'neutral'))
        if avId == localAvatar.doId:
            self.movie.append(Func(self.finishInteraction))
            self.movie.append(Func(self.movieDone))
            if hasattr(self, 'doResultDialog'):
                self.movie.append(Func(self.doResultDialog))
        self.movie.start()

    def interactionDenied(self, avId):
        if avId == localAvatar.doId:
            self.finishInteraction()
예제 #44
0
class Heightfield():
	'''
	classdocs
	'''

	
	def __init__(self, name, heightmap = None, bruteforce = True, 
				 blockSize = 32, near = 512, far = 2048):
		self.geomRoot = None
		self.collRoot = None
		self.textures = []
		self.updateTask = None
		self.name = name
		geomip = GeoMipTerrain("Heightfield:" + name)
		
		self.terrainRoot = NodePath("Terrain:" + name)
		
		self.geomip = geomip
		geomRoot = geomip.getRoot()
		self.geomRoot = geomRoot
		geomRoot.reparentTo(self.terrainRoot)
		
		geomRoot.setPos( -MAPSIZE/2, -MAPSIZE/2, -HEIGHTSCALE/2)
		geomRoot.setSx(HORIZONTALSCALE)
		geomRoot.setSy(HORIZONTALSCALE)
		geomRoot.setSz(HEIGHTSCALE)
		
		geomip.setBruteforce(bruteforce)
		geomip.setBlockSize(blockSize)
		geomip.setNear(near)
		geomip.setFar(far)
		
		self.collRoot = self.terrainRoot.attachNewNode("blagablaga")
		
		if heightmap != None:
			self.loadHeightmap(heightmap)
	
	def genCollTree(self):
		
		tempNode = NodePath('tempNode')
		toOctreefy = self.geomRoot.copyTo(tempNode)
		toOctreefy.flattenLight()
		print "begin octreefy"
		collRoot = nodeOctree.octreefy(toOctreefy)
		print "end octreefy"
		tempNode.removeNode()
		self.collRoot.removeNode()
		self.collRoot = collRoot
		collRoot.reparentTo(self.terrainRoot)
	
	def getRoot(self):
		return self.terrainRoot
	
	def getGeomRoot(self):
		return self.GeomRoot
	
	def loadHeightmap(self, heightmap):
		bruteforceChange = False
		if self.geomip.getBruteforce() == False:
			bruteforceChange = True
		
		self.geomip.setHeightfield(heightmap)
		#if bruteforce is off, turn it on for collTree generation
		if bruteforceChange:
			self.geomip.setBruteforce(True)
		print "generating heightfield"
		self.geomip.generate()
		self.geomip.update()
		self.genCollTree()
		if bruteforceChange:
			self.geomip.setBruteforce(False)
			self.geomip.generate()
			self.geomip.update()
		print "heightfield generated"
	
	def addTexture(self, texture, scale = 1.0, name = 'texture'):
		ts = TextureStage(name)
		self.textures.append(ts)
		self.geomRoot.setTexScale(ts, scale, scale)
		self.geomRoot.setTexture(ts, texture, 1 )
		
	def updateFocalPoint(self, task):
		posX = base.camera.getX(render)  + MAPSIZE/2
		posY = base.camera.getY(render)  + MAPSIZE/2
		self.geomip.setFocalPoint(posX, posY)
		self.geomip.update()
		return task.again
	
	def enable(self):
		self.updateTask = taskMgr.doMethodLater(0.1, self.updateFocalPoint, 
												'update_heightfield')
		self.collRoot.reparentTo(self.terrainRoot)
	
	def disable(self):
		if self.updateTask != None:
			taskMgr.remove(self.updateTask)
			self.updateTask = None
		self.collRoot.detachNode()
	
	def hide(self):
		self.terrainRoot.hide()
		
		self.disable()
	
	def show(self):
		self.terrainRoot.show()
		
		self.enable()
	
	def world2MapPos( self, worldPos ):
		result = None
		posX = (worldPos[0] + MAPSIZE/2.0) / HORIZONTALSCALE
		posY = (worldPos[1] + MAPSIZE/2.0) / HORIZONTALSCALE
		result = (posX,posY)
		return result
	
	def getElevation( self, worldPos ):
		result = None
		if abs(worldPos[0]) <= MAPSIZE/2.0 and abs(worldPos[1]) <= MAPSIZE/2.0:
			mapPos = self.world2MapPos(worldPos)
			mapElevation = self.geomip.getElevation( mapPos[0] , mapPos[1] )
			result = (mapElevation * HEIGHTSCALE) - HEIGHTSCALE/2
		return result
예제 #45
0
class CogdoMazeDoor:
    def __init__(self, closedDoorModel, openDoorModel):
        self.model = NodePath("CogdoMazeDoor")
        self.model.setPos(0, 0, 0)
        self.model.reparentTo(render)

        self.closedDoorModel = closedDoorModel
        self.closedDoorModel.reparentTo(self.model)

        self.openDoorModel = openDoorModel
        self.openDoorModel.reparentTo(self.model)
        self.openDoorModel.stash()

        self.lockId2lock = {}
        self._open = False
        self.revealed = False
        self.players = []

        self._initCollisions()

    def setPosition(self, x, y):
        self.model.setPos(x, y, 2.5)

    def _initCollisions(self):
        name = "CogdoMazeDoor"
        collSphere = CollisionSphere(0, 0, 0.0, 0.25)
        collSphere.setTangible(0)
        collNode = CollisionNode(name)
        collNode.setFromCollideMask(ToontownGlobals.CatchGameBitmask)
        collNode.addSolid(collSphere)
        self.collNP = self.model.attachNewNode(collNode)

        self.enterCollisionEventName = "enter" + name

    def destroy(self):
        self.model.removeNode()
        del self.model
        del self.openDoorModel
        del self.closedDoorModel

        for lock in self.lockId2lock.values():
            lock.destroy()
        del self.lockId2lock

    def onstage(self):
        self.model.unstash()

    def offstage(self):
        self.model.stash()

    def open(self):
        self._open = True
        self.closedDoorModel.stash()
        self.openDoorModel.unstash()

    def close(self):
        self._open = False
        self.closedDoorModel.unstash()
        self.openDoorModel.stash()

    def addLock(self, lock):
        self.lockId2lock[lock.id] = lock

    def unlock(self, lockId):
        lock = self.lockId2lock.get(lockId)

        if lock is not None and lock.isLocked():
            lock.unlock()
            return True

        return False

    def getLocks(self):
        return self.lockId2lock.values()

    def getLock(self, lockId):
        return self.lockId2lock.get(lockId)

    def isLocked(self):
        return True in [lock.isLocked() for lock in self.lockId2lock.values()]

    def playerEntersDoor(self, player):
        self.players.append(player)

    def getPlayerCount(self):
        return len(self.players)
    def getShip(
        self,
        shipClass,
        style=ShipGlobals.Styles.Undefined,
        logo=ShipGlobals.Logos.Undefined,
        hullDesign=None,
        detailLevel=2,
        wantWheel=True,
        hullMaterial=None,
        sailMaterial=None,
        sailPattern=None,
        prowType=None,
    ):
        Ship = Ship
        import pirates.ship

        modelClass = ShipGlobals.getModelClass(shipClass)
        shipConfig = ShipGlobals.getShipConfig(shipClass)
        if style == ShipGlobals.Styles.Undefined:
            style = shipConfig["defaultStyle"]

        complexCustomization = 0
        if sailPattern and sailMaterial and hullMaterial or SailReplace.has_key(shipClass):
            complexCustomization = 1

        if not prowType:
            prowType = shipConfig["prow"]

        if not hullMaterial:
            hullMaterial = style

        if not sailMaterial:
            if SailReplace.has_key(shipClass):
                sailMaterial = SailReplace[shipClass]
            else:
                sailMaterial = style

        if not sailPattern:
            sailPattern = style

        shipHullTexture = ShipBlueprints.getShipTexture(hullMaterial)
        shipTextureSail = ShipBlueprints.getShipTexture(sailMaterial)
        logoTex = None
        if logo:
            logoTex = ShipBlueprints.getLogoTexture(logo)

        sailPatternTex = None
        if sailPattern:
            sailPatternTex = ShipBlueprints.getSailTexture(sailPattern)

        self.notify.debug("%s %s" % (sailPattern, logo))
        if logo == ShipGlobals.Logos.Undefined:
            logo = shipConfig["sailLogo"]

        if logo in ShipGlobals.MAST_LOGO_PLACEMENT_LIST:
            placeLogos = 1
        else:
            placeLogos = 0
        if modelClass <= ShipGlobals.INTERCEPTORL3:
            mastHax = True
        else:
            mastHax = False
        customHull = hullDesign is not None
        if not logo != 0:
            pass
        customMasts = sailPattern != 0
        hull = self.getHull(modelClass, customHull)
        breakAnims = {}
        metaAnims = {}
        hitAnims = {}
        root = NodePath("Ship")
        hull.locators.reparentTo(root)
        charRoot = root.attachNewNode(Character("ShipChar"))
        collisions = root.attachNewNode("collisions")
        lodNode = charRoot.attachNewNode(LODNode("lod"))
        if detailLevel == 0:
            lodNode.node().addSwitch(200, 0)
            lodNode.node().addSwitch(800, 200)
            lodNode.node().addSwitch(100000, 800)
            high = lodNode.attachNewNode("high")
            low = lodNode.attachNewNode("low")
            med = NodePath("med")
            superlow = lodNode.attachNewNode("superlow")
        elif detailLevel == 1:
            lodNode.node().addSwitch(300, 0)
            lodNode.node().addSwitch(1000, 300)
            lodNode.node().addSwitch(2000, 1000)
            lodNode.node().addSwitch(100000, 2000)
            high = lodNode.attachNewNode("high")
            med = lodNode.attachNewNode("med")
            low = lodNode.attachNewNode("low")
            superlow = lodNode.attachNewNode("superlow")
        else:
            lodNode.node().addSwitch(750, 0)
            lodNode.node().addSwitch(3000, 750)
            lodNode.node().addSwitch(8000, 3000)
            lodNode.node().addSwitch(100000, 8000)
            high = lodNode.attachNewNode("high")
            med = lodNode.attachNewNode("med")
            low = lodNode.attachNewNode("low")
            superlow = lodNode.attachNewNode("superlow")
        mastSetup = ShipGlobals.getMastSetup(shipClass)
        for data in [
            (0, "location_mainmast_0"),
            (1, "location_mainmast_1"),
            (2, "location_mainmast_2"),
            (3, "location_aftmast*"),
            (4, "location_foremast*"),
        ]:
            mastData = mastSetup.get(data[0])
            if mastData:
                mast = self.mastSets[mastData[0]].getMastSet(mastData[1] - 1, customMasts)
                mastRoot = hull.locators.find("**/%s" % data[1]).getTransform(hull.locators)
                model = NodePath(mast.charRoot)
                model.setTransform(mastRoot)
                if complexCustomization:
                    model.setTexture(shipTextureSail)

                useLogoTex = logoTex
                if placeLogos:
                    mastNum = data[0]
                    if mastNum not in ShipGlobals.MAST_LOGO_PLACEMENT.get(modelClass):
                        useLogoTex = None

                charBundle = mast.charRoot.getBundle(0)
                if data[0] < 3:
                    for side in ["left", "right"]:
                        ropeNode = hull.locators.find("**/location_ropeLadder_%s_%s" % (side, data[0]))
                        if ropeNode:
                            transform = ropeNode.getTransform(NodePath(mast.charRoot))
                            charBundle.findChild("def_ladder_0_%s" % side).applyFreeze(transform)
                            continue

                if sailPatternTex and useLogoTex:
                    for node in model.findAllMatches("**/sails"):
                        node.setTextureOff(TextureStage.getDefault())
                        node.setTexture(self.colorLayer, sailPatternTex)
                        node.setTexture(self.logoLayer, logoTex)
                        node.setTexture(self.vertLayer, shipTextureSail)
                        node.setTexture(self.baseLayer, shipTextureSail)

                elif sailPatternTex:
                    for node in model.findAllMatches("**/sails"):
                        node.setTextureOff(TextureStage.getDefault())
                        node.setTexture(self.colorLayer, sailPatternTex)
                        node.setTexture(self.vertLayer, shipTextureSail)
                        node.setTexture(self.baseLayer, shipTextureSail)

                elif useLogoTex:
                    for node in model.findAllMatches("**/sails"):
                        node.setTextureOff(TextureStage.getDefault())
                        node.setTexture(self.logoLayerNoColor, logoTex)
                        node.setTexture(self.vertLayer, shipTextureSail)
                        node.setTexture(self.baseLayer, shipTextureSail)

                model.flattenLight()
                if detailLevel == 0:
                    model.find("**/low").copyTo(high)
                    model.find("**/low").copyTo(low)
                    model.find("**/superlow").copyTo(superlow)
                elif detailLevel == 1:
                    model.find("**/med").copyTo(high)
                    model.find("**/med").copyTo(med)
                    low.node().stealChildren(model.find("**/low").node())
                    superlow.node().stealChildren(model.find("**/superlow").node())
                elif detailLevel == 2:
                    high.node().stealChildren(model.find("**/high").node())
                    med.node().stealChildren(model.find("**/med").node())
                    low.node().stealChildren(model.find("**/low").node())
                    superlow.node().stealChildren(model.find("**/superlow").node())

                mastRoot = mast.collisions.find("**/collision_masts")
                if modelClass > ShipGlobals.INTERCEPTORL3 or data[0] != 3:
                    mastCode = str(data[0])
                    mastRoot.setTag("Mast Code", mastCode)
                else:
                    mastRoot.setName("colldision_sub_mast")
                    mastRoot.reparentTo(collisions.find("**/collision_masts"))
                    mastCode = "0"
                for coll in mast.collisions.findAllMatches("**/collision_sail_*"):
                    coll.setName("Sail-%s" % data[0])
                    coll.setTag("Mast Code", mastCode)

                for coll in mast.collisions.findAllMatches("**/sail_*"):
                    coll.setName("Sail-%s" % data[0])
                    coll.setTag("Mast Code", mastCode)

                collisions.node().stealChildren(mast.collisions.node())
                charBundle = mast.charRoot.getBundle(0)
                if mastHax and data[0] == 3:
                    breakAnims[0][0].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.breakAnim[0], -1, MastSubset, True), "1"
                    )
                    breakAnims[0][1].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.breakAnim[1], -1, MastSubset, True), "1"
                    )
                    tempHit = hitAnims[0]
                    tempHit[0].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.hitAnim, -1, HitMastSubset, True), "1"
                    )
                    tempHit[1].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.hitAnim, -1, PartSubset(), True), "1"
                    )
                else:
                    breakAnims[data[0]] = (AnimControlCollection(), AnimControlCollection())
                    breakAnims[data[0]][0].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.breakAnim[0], -1, MastSubset, True), "0"
                    )
                    breakAnims[data[0]][1].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.breakAnim[1], -1, MastSubset, True), "0"
                    )
                    tempHit = [AnimControlCollection(), AnimControlCollection()]
                    tempHit[0].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.hitAnim, -1, HitMastSubset, True), "0"
                    )
                    tempHit[1].storeAnim(
                        charBundle.loadBindAnim(loader.loader, mast.hitAnim, -1, PartSubset(), True), "0"
                    )
                    hitAnims[data[0]] = tempHit
                for (anim, fileName) in mast.metaAnims.iteritems():
                    if anim not in metaAnims:
                        metaAnims[anim] = AnimControlCollection()

                    if anim not in MissingAnims.get(modelClass, []):
                        ac = charBundle.loadBindAnim(loader.loader, fileName, -1, SailSubset, True)
                        if ac:
                            metaAnims[anim].storeAnim(ac, str(metaAnims[anim].getNumAnims()))

                charRoot.node().combineWith(mast.charRoot)
                continue

        if self.wantProws and prowType:
            (highSprit, medSprit, lowSprit) = self.sprits[prowType].getAsset()
            transform = hull.locators.find("**/location_bowsprit").getTransform(hull.locators)
            highSprit.setTransform(transform)
            medSprit.setTransform(transform)
            lowSprit.setTransform(transform)
            highSprit.reparentTo(hull.geoms[0])
            medSprit.reparentTo(hull.geoms[1])
            lowSprit.reparentTo(hull.geoms[2])

        if wantWheel:
            shipWheel = ShipBlueprints.getWheel()
            wheelPoint = hull.locators.find("**/location_wheel;+s").getTransform(hull.locators)
            shipWheel.setTransform(wheelPoint)
            shipWheel.flattenLight()
            shipWheel.find("**/collisions").copyTo(collisions)
            hull.geoms[0].node().stealChildren(shipWheel.find("**/high").node())
            hull.geoms[1].node().stealChildren(shipWheel.find("**/med").node())
            hull.geoms[2].node().stealChildren(shipWheel.find("**/low").node())

        if complexCustomization:
            hull.geoms[0].setTexture(shipHullTexture)
            hull.geoms[0].flattenLight()
            hull.geoms[1].setTexture(shipHullTexture)
            hull.geoms[1].flattenLight()
            hull.geoms[2].setTexture(shipHullTexture)
            hull.geoms[2].flattenLight()
            hull.geoms[3].setTexture(shipHullTexture)
            hull.geoms[3].flattenLight()

        high.attachNewNode(ModelNode("non-animated")).node().stealChildren(hull.geoms[0].node())
        med.attachNewNode(ModelNode("non-animated")).node().stealChildren(hull.geoms[1].node())
        low.attachNewNode(ModelNode("non-animated")).node().stealChildren(hull.geoms[2].node())
        superlow.attachNewNode(ModelNode("non-animated")).node().stealChildren(hull.geoms[3].node())
        collisions.node().stealChildren(hull.collisions.node())
        hull.locators.stash()
        charRoot.flattenStrong()
        ship = Ship.Ship(shipClass, root, breakAnims, hitAnims, metaAnims, collisions, hull.locators)
        if not complexCustomization:
            ship.char.setTexture(shipHullTexture)

        return ship
예제 #47
0
파일: Minimap.py 프로젝트: Kealigal/POS2013
class AreaMap(Map):
    
    def __init__(self, area):
        Map.__init__(self, 'map-' + area.getName())
        self.capturePoints = { }
        mapNode = area.getMapNode()
        if mapNode and not mapNode.isEmpty():
            geom = mapNode.getChild(0)
            geom.setScale(mapNode.getScale())
            geom.flattenStrong()
            mapNode.setScale(1)
            self.worldNode = mapNode
            self.map = self.worldNode.copyTo(NodePath())
            (a, b) = self.map.getTightBounds()
            diff = b - a
            h = diff[1]
            w = diff[0]
        else:
            self.worldNode = area
            self.map = NodePath('no map found')
            (a, b) = self.worldNode.geom.getTightBounds()
            diff = b - a
            h = diff[1]
            w = diff[0]
        ratio = h / w
        if ratio < 0.98999999999999999:
            normalScale = 2 / w
            screenScale = 1
        else:
            normalScale = 2 / h
            screenScale = 0.75
        self.map.clearTransform()
        self.map.show()
        self.screenNode = NodePath('Minimap-screenNode')
        self.screenNode.setP(90)
        self.screenNode.setScale(screenScale * normalScale)
        self.screenNode.hide()
        self.map.reparentTo(self.screenNode)
        self.mapOverlay = self.map.attachNewNode('mapOverlay')
        self.mapOverlay.wrtReparentTo(self.screenNode)
        self.radarTransformNode = NodePath('radarTransform')
        self.radarTransformNode.setScale(self.worldNode.getScale()[0])
        self.map.instanceTo(self.radarTransformNode)
        localAvatar.guiMgr.addMinimap(self)
        if self.allowOnScreen():
            self.addObject(MinimapFootprint(area))
        
        self.shops = set()
        if self.allowOnScreen():
            if area.getUniqueId() not in [
                LocationIds.RAVENS_COVE_ISLAND]:
                for shop in area.getShopNodes():
                    uid = shop.getTag('Uid')
                    shopType = shop.getTag('ShopType')
                    self.addObject(MinimapShop(uid, shop, shopType))
                
            
            self.map.findAllMatches('**/=Holiday').stash()
            if base.cr.newsManager:
                for holiday in base.cr.newsManager.getHolidayList():
                    self.handleHolidayStarted(area, HolidayGlobals.getHolidayName(holiday))
                
            
        
        self.zoomLevels = area.getZoomLevels()
        self.accept('landMapRadarAxisChanged', self.setRadarAxis)

    
    def destroy(self):
        self.ignore('landMapRadarAxisChanged')
        if hasattr(base, 'localAvatar'):
            localAvatar.guiMgr.removeMinimap(self)
        
        for shop in self.shops:
            self.removeObject(shop)
        
        self.shops = set()
        for holiday in self.capturePoints.keys():
            zones = self.capturePoints.pop(holiday, { })
            for object in zones.itervalues():
                self.removeObject(object)
            
        
        Map.destroy(self)

    
    def allowOnScreen(self):
        return self.map.find('minimap-card').isEmpty()

    
    def getZoomLevels(self):
        return self.zoomLevels

    
    def getWorldNode(self):
        return self.worldNode

    
    def getScreenNode(self):
        return self.screenNode

    
    def getOverlayNode(self):
        return self.mapOverlay

    
    def getCapturePoint(self, holidayId, zone):
        if self.capturePoints.has_key(holidayId):
            return self.capturePoints[holidayId][zone]
        

    
    def updateTask(self, task):
        self.update()
        return task.cont

    
    def update(self):
        for obj in self.objects:
            obj.updateOnMap(self)
        

    
    def addObject(self, object):
        Map.addObject(self, object)
        mapNode = object.getMapNode()
        mapNode.reparentTo(self.map, sort = object.SORT)
        object.getOverlayNode().reparentTo(self.mapOverlay, sort = object.SORT)
        object.addedToMap(self)

    
    def removeObject(self, object):
        Map.removeObject(self, object)
        object.getMapNode().detachNode()
        object.getOverlayNode().detachNode()
        object.removedFromMap(self)

    
    def updateRadarTransform(self, av):
        if self.radarAxis == Options.RadarAxisMap:
            self.radarTransformNode.setPosHprScale(-av.getPos(self.worldNode), VBase3(0), VBase3(1))
        else:
            holdHpr = av.getHpr()
            av.setH(camera.getH(render) - self.worldNode.getH(render))
            self.radarTransformNode.setTransform(self.worldNode.getTransform(av))
            av.setHpr(holdHpr)
        localAvatar.guiMgr.radarGui.updateDial(self)

    
    def getRadarNode(self):
        return self.radarTransformNode

    
    def handleHolidayStarted(self, area, holiday):
        self.map.findAllMatches('**/=Holiday=%s;+s' % (holiday,)).unstash()
        for node in area.getCapturePointNodes(holiday):
            zones = self.capturePoints.setdefault(holiday, { })
            zone = int(node.getTag('Zone'))
            if zone not in zones:
                object = MinimapCapturePoint(node, holiday, zone)
                zones[zone] = object
                self.addObject(object)
                continue
        

    handleHolidayStarted = report(types = [
        'frameCount',
        'args'], dConfigParam = 'minimap')(handleHolidayStarted)
    
    def handleHolidayEnded(self, area, holiday, override = False):
        if holiday in InvasionGlobals.INVASION_IDS and not override:
            taskMgr.doMethodLater(10, self.handleInvasionEnded, 'handleInvasionEnded', extraArgs = [
                area,
                holiday])
        else:
            self.map.findAllMatches('**/=Holiday=%s;+s' % (holiday,)).stash()
            for object in self.capturePoints.pop(holiday, { }).itervalues():
                self.removeObject(object)
            

    handleHolidayEnded = report(types = [
        'frameCount',
        'args'], dConfigParam = 'minimap')(handleHolidayEnded)
    
    def handleInvasionEnded(self, area, holiday):
        if not localAvatar.guiMgr.invasionScoreboard:
            self.map.findAllMatches('**/=Holiday=%s;+s' % (holiday,)).stash()
            for object in self.capturePoints.pop(holiday, { }).itervalues():
                self.removeObject(object)
예제 #48
0
class Entity(ActorNode):
    def __init__(self, name, world, pos):
        ActorNode.__init__(self, name)

        self.nodePath = NodePath(self)

        self.world = world

        # init the model or the Actor
        self.model = self.getModel()
        self.model.reparentTo(self.nodePath)

        self.nodePath.setPos(*pos)

        self.prevPos = self.nodePath.getPos()

        # collision detection
        fromObject = self.nodePath.attachNewNode(CollisionNode(name))
        self.addSolids(fromObject)
        fromObject.show()

        # setup the ground ray, needed for detecting the ground
        groundRay = CollisionRay()
        groundRay.setOrigin(0, 0, 1000)
        groundRay.setDirection(0, 0, -1)
        groundCol = CollisionNode('groundRay')
        groundCol.addSolid(groundRay)
        groundCol.setFromCollideMask(BitMask32.bit(0))
        groundCol.setIntoCollideMask(BitMask32.allOff())
        groundColNp = base.camera.attachNewNode(groundCol)
        self.groundHandler = CollisionHandlerQueue()
        self.world.cTrav.addCollider(groundColNp, self.groundHandler)

        #        self.world.cTrav.addCollider(fromObject, self.world.pusher)
        #        self.world.pusher.addCollider(fromObject, self.nodePath)

        self.postInit()

    def postInit(self):
        '''Subclasses can override this method to add stuff after the init'''
        pass

    def addSolids(self, fromObject):
        '''Subclasses can override this method to add sollids for collision
        detection to match their model and size. Below is a default'''
        fromObject.node().addSolid(CollisionSphere(0, 0, 0, 0.5))

    def validateMove(self):
        # Make sure the entity is above the ground.
        groundEntry = self.world.getGroundEntry(self.groundHandler)
        if groundEntry is not None and groundEntry.getIntoNode().getName(
        ) == 'terrain':
            self.nodePath.setZ(groundEntry.getSurfacePoint(render).getZ())
        else:
            self.nodePath.setPos(self.prevPos)

    def getGroundEntry(self, collisionHandler):
        '''Deprecated. Not used anymore'''
        # Put all the collision entries into a Python list so we can sort it,
        # properly.
        entries = []
        for i in range(collisionHandler.getNumEntries()):
            entries.append(collisionHandler.getEntry(i))

        # Sort the list by the collision points' Z values, making sure the
        # highest value ends up at the front of the list.
        entries.sort(lambda x, y: cmp(
            y.getSurfacePoint(render).getZ(),
            x.getSurfacePoint(render).getZ()))

        if len(entries) > 0:
            return entries[0]
        else:
            return None
예제 #49
0
class CogdoFlyingLevel(DirectObject):
    notify = directNotify.newCategory('CogdoFlyingLevel')

    def __init__(self, parent, frameModel, startPlatformModel, endPlatformModel, quadLengthUnits, quadVisibilityAhead, quadVisibiltyBehind):
        self.parent = parent
        self.quadLengthUnits = quadLengthUnits
        self._halfQuadLengthUnits = quadLengthUnits / 2.0
        self.quadVisibiltyAhead = quadVisibilityAhead
        self.quadVisibiltyBehind = quadVisibiltyBehind
        self._frameModel = frameModel
        self.root = NodePath('CogdoFlyingLevel')
        self.quadrantRoot = NodePath('QuadrantsRoot')
        self.quadrantRoot.reparentTo(self.root)
        self._startPlatformModel = startPlatformModel
        self._startPlatformModel.reparentTo(self.root)
        self._startPlatformModel.setZ(Globals.Level.StartPlatformHeight)
        self._endPlatformModel = endPlatformModel
        self._endPlatformModel.reparentTo(self.root)
        self._endPlatformModel.setZ(Globals.Level.EndPlatformHeight)
        self.wallR = self._frameModel.find('**/wallR')
        self.wallL = self._frameModel.find('**/wallL')
        self._exit = CogdoGameExit()
        self._exit.reparentTo(self._endPlatformModel)
        loc = self._endPlatformModel.find('**/exit_loc')
        offset = loc.getPos(render)
        self._exit.setPos(render, offset)
        self.quadrants = []
        self.visibleQuadIndices = []
        self._numQuads = 0
        self._currentQuadNum = -1
        self._camera = None
        self._initCollisions()
        self.upLimit = self._frameModel.find('**/limit_up').getZ(render)
        self.downLimit = self._frameModel.find('**/limit_down').getZ(render)
        self.leftLimit = self._frameModel.find('**/limit_left').getX(render) - 30.0
        self.rightLimit = self._frameModel.find('**/limit_right').getX(render) + 30.0
        self.backLimit = -self.quadLengthUnits
        self.forwardLimit = self.quadLengthUnits * 20
        self._frameModel.flattenStrong()
        self.gatherableFactory = CogdoFlyingGatherableFactory()
        self.obstacleFactory = CogdoFlyingObstacleFactory()
        return

    def getExit(self):
        return self._exit

    def getBounds(self):
        return ((self.leftLimit, self.rightLimit), (self.backLimit, self.forwardLimit), (self.downLimit, self.upLimit))

    def getGatherable(self, serialNum):
        for quadrant in self.quadrants:
            for gatherable in quadrant.gatherables:
                if gatherable.serialNum == serialNum:
                    return gatherable

        return None

    def ready(self):
        self.gatherableFactory.destroy()
        del self.gatherableFactory
        self.obstacleFactory.destroy()
        del self.obstacleFactory
        self._initStartEndPlatforms()
        self._frameModel.reparentTo(self.root)
        self.root.reparentTo(self.parent)
        self.root.stash()

    def _initStartEndPlatforms(self):
        self.startPlatform = CogdoFlyingPlatform(self._startPlatformModel, Globals.Level.PlatformTypes.StartPlatform)
        self.endPlatform = CogdoFlyingPlatform(self._endPlatformModel, Globals.Level.PlatformTypes.EndPlatform)
        self._endPlatformModel.setY(self.convertQuadNumToY(self._numQuads))
        self.backLimit = self._startPlatformModel.getY(render) - Globals.Level.StartPlatformLength * 0.7
        self.forwardLimit = self._endPlatformModel.getY(render) + Globals.Level.EndPlatformLength * 0.7

    def _initCollisions(self):
        self.collPlane = CollisionPlane(Plane(Vec3(0, 0, 1.0), Point3(0, 0, 10)))
        self.collPlane.setTangible(0)
        self.collNode = CollisionNode('fogPlane')
        self.collNode.setIntoCollideMask(OTPGlobals.FloorBitmask)
        self.collNode.addSolid(self.collPlane)
        self.collNodePath = self.root.attachNewNode(self.collNode)
        self.collNodePath.hide()

    def destroy(self):
        del self.collPlane
        self.collNodePath.removeNode()
        del self.collNodePath
        del self.collNode
        for quadrant in self.quadrants:
            quadrant.destroy()

        self._exit.destroy()
        del self._exit
        self.root.removeNode()
        del self.root

    def onstage(self):
        self.root.unstash()
        self.update(0.0)

    def offstage(self):
        self.root.stash()

    def start(self, startTime = 0.0):
        self._startTime = startTime

    def stop(self):
        pass

    def getLength(self):
        return self.quadLengthUnits * self.getNumQuadrants()

    def appendQuadrant(self, model):
        quadrant = CogdoFlyingLevelQuadrant(self._numQuads, model, self, self.root)
        if self._numQuads == 0:
            quadrant.generateGatherables(self._startPlatformModel)
        quadrant.offstage()
        self.quadrants.append(quadrant)
        self._numQuads = len(self.quadrants)

    def getNumQuadrants(self):
        return self._numQuads

    def setCamera(self, camera):
        self._camera = camera

    def getCameraActualQuadrant(self):
        camY = self._camera.getY(render)
        y = self.root.getY(render)
        return self.convertYToQuadNum(camY - y)

    def update(self, dt = 0.0):
        if self._camera is None:
            return
        else:
            quadNum = clamp(self.getCameraActualQuadrant(), 0, self._numQuads - 1)
            if quadNum < self._numQuads:
                self.quadrants[quadNum].update(dt)
                if quadNum + 1 < self._numQuads:
                    self.quadrants[quadNum + 1].update(dt)
                if quadNum != self._currentQuadNum:
                    self._switchToQuadrant(quadNum)
            return

    def _switchToQuadrant(self, quadNum):
        self.visibleQuadIndices = []
        if quadNum >= 0:
            if quadNum > 0:
                self.quadrants[max(quadNum - self.quadVisibiltyBehind, 0)].onstage()
            for i in xrange(quadNum, min(quadNum + self.quadVisibiltyAhead + 1, self._numQuads)):
                self.quadrants[i].onstage()
                self.visibleQuadIndices.append(i)
                if i == 0:
                    self.startPlatform.onstage()
                elif i == self._numQuads - 1:
                    self.endPlatform.onstage()

        self._currentQuadNum = quadNum
        for i in range(0, max(self._currentQuadNum - self.quadVisibiltyBehind, 0)) + range(min(self._currentQuadNum + self.quadVisibiltyAhead + 1, self._numQuads), self._numQuads):
            self.quadrants[i].offstage()
            if i == 0:
                self.startPlatform.offstage()
            elif i == self._numQuads - 1:
                self.endPlatform.offstage()

    def convertQuadNumToY(self, quadNum):
        return quadNum * self.quadLengthUnits

    def convertYToQuadNum(self, y):
        return int(y / self.quadLengthUnits)

    def convertCenterYToQuadNum(self, y):
        return self.convertYToQuadNum(y + self._halfQuadLengthUnits)
class PartyCog(FSM):
    notify = directNotify.newCategory('PartyCog')
    HpTextGenerator = TextNode('HpTextGenerator')
    hpText = None
    height = 7

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

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

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

    def enterStatic(self):
        pass

    def exitStatic(self):
        pass

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def getHeadLocation(self):
        self.actor.getJoints(jointName='head')[0].getNetTransform(self.temp_transform)
        self.head_locator.setMat(self.temp_transform)
        return self.head_locator.getZ(self.root)
예제 #51
0
class Sprite2d:

	class Cell:
		def __init__(self, col, row):
			self.col = col
			self.row = row

		def __str__(self):
			return "Cell - Col %d, Row %d" % (self.col, self.row)

	class Animation:
		def __init__(self, cells, fps):
			self.cells = cells
			self.fps = fps
			self.playhead = 0

	ALIGN_CENTER = "Center"
	ALIGN_LEFT = "Left"
	ALIGN_RIGHT = "Right"
	ALIGN_BOTTOM = "Bottom"
	ALIGN_TOP = "Top"

	TRANS_ALPHA = TransparencyAttrib.MAlpha
	TRANS_DUAL = TransparencyAttrib.MDual
	# One pixel is divided by this much. If you load a 100x50 image with PIXEL_SCALE of 10.0
	# you get a card that is 1 unit wide, 0.5 units high
	PIXEL_SCALE = 20.0

	def __init__(self, image_path, rowPerFace, name=None,\
				  rows=1, cols=1, scale=1.0,\
				  twoSided=False, alpha=TRANS_ALPHA,\
				  repeatX=1, repeatY=1,\
				  anchorX=ALIGN_CENTER, anchorY=ALIGN_BOTTOM):
		"""
		Create a card textured with an image. The card is sized so that the ratio between the
		card and image is the same.
		"""

		global SpriteId
		self.spriteNum = str(SpriteId)
		SpriteId += 1

		scale *= self.PIXEL_SCALE

		self.animations = {}

		self.scale = scale
		self.repeatX = repeatX
		self.repeatY = repeatY
		self.flip = {'x':False,'y':False}
		self.rows = rows
		self.cols = cols

		self.currentFrame = 0
		self.currentAnim = None
		self.loopAnim = False
		self.frameInterrupt = True

		# Create the NodePath
		if name:
			self.node = NodePath("Sprite2d:%s" % name)
		else:
			self.node = NodePath("Sprite2d:%s" % image_path)

		# Set the attribute for transparency/twosided
		self.node.node().setAttrib(TransparencyAttrib.make(alpha))
		if twoSided:
			self.node.setTwoSided(True)

		# Make a filepath
		self.imgFile = Filename(image_path)
		if self.imgFile.empty():
			raise IOError, "File not found"

		# Instead of loading it outright, check with the PNMImageHeader if we can open
		# the file.
		imgHead = PNMImageHeader()
		if not imgHead.readHeader(self.imgFile):
			raise IOError, "PNMImageHeader could not read file. Try using absolute filepaths"

		# Load the image with a PNMImage
		image = PNMImage()
		image.read(self.imgFile)

		self.sizeX = image.getXSize()
		self.sizeY = image.getYSize()

		# We need to find the power of two size for the another PNMImage
		# so that the texture thats loaded on the geometry won't have artifacts
		textureSizeX = self.nextsize(self.sizeX)
		textureSizeY = self.nextsize(self.sizeY)

		# The actual size of the texture in memory
		self.realSizeX = textureSizeX
		self.realSizeY = textureSizeY

		self.paddedImg = PNMImage(textureSizeX, textureSizeY)
		if image.hasAlpha():
			self.paddedImg.alphaFill(0)
		# Copy the source image to the image we're actually using
		self.paddedImg.blendSubImage(image, 0, 0)
		# We're done with source image, clear it
		image.clear()

		# The pixel sizes for each cell
		self.colSize = self.sizeX/self.cols
		self.rowSize = self.sizeY/self.rows

		# How much padding the texture has
		self.paddingX = textureSizeX - self.sizeX
		self.paddingY = textureSizeY - self.sizeY

		# Set UV padding
		self.uPad = float(self.paddingX)/textureSizeX
		self.vPad = float(self.paddingY)/textureSizeY

		# The UV dimensions for each cell
		self.uSize = (1.0 - self.uPad) / self.cols
		self.vSize = (1.0 - self.vPad) / self.rows
	
		self.cards = []
		self.rowPerFace = rowPerFace
		for i in range(len(rowPerFace)):
			card = CardMaker("Sprite2d-Geom")

			# The positions to create the card at
			if anchorX == self.ALIGN_LEFT:
				posLeft = 0
				posRight = (self.colSize/scale)*repeatX
			elif anchorX == self.ALIGN_CENTER:
				posLeft = -(self.colSize/2.0/scale)*repeatX
				posRight = (self.colSize/2.0/scale)*repeatX
			elif anchorX == self.ALIGN_RIGHT:
				posLeft = -(self.colSize/scale)*repeatX
				posRight = 0

			if anchorY == self.ALIGN_BOTTOM:
				posTop = 0
				posBottom = (self.rowSize/scale)*repeatY
			elif anchorY == self.ALIGN_CENTER:
				posTop = -(self.rowSize/2.0/scale)*repeatY
				posBottom = (self.rowSize/2.0/scale)*repeatY
			elif anchorY == self.ALIGN_TOP:
				posTop = -(self.rowSize/scale)*repeatY
				posBottom = 0

			card.setFrame(posLeft, posRight, posTop, posBottom)
			card.setHasUvs(True)
			self.cards.append(self.node.attachNewNode(card.generate()))
			self.cards[-1].setH(i * 360/len(rowPerFace))

		# Since the texture is padded, we need to set up offsets and scales to make
		# the texture fit the whole card
		self.offsetX = (float(self.colSize)/textureSizeX)
		self.offsetY = (float(self.rowSize)/textureSizeY)

		# self.node.setTexScale(TextureStage.getDefault(), self.offsetX * repeatX, self.offsetY * repeatY)
		# self.node.setTexOffset(TextureStage.getDefault(), 0, 1-self.offsetY)
		
		self.texture = Texture()

		self.texture.setXSize(textureSizeX)
		self.texture.setYSize(textureSizeY)
		self.texture.setZSize(1)

		# Load the padded PNMImage to the texture
		self.texture.load(self.paddedImg)

		self.texture.setMagfilter(Texture.FTNearest)
		self.texture.setMinfilter(Texture.FTNearest)

		#Set up texture clamps according to repeats
		if repeatX > 1:
			self.texture.setWrapU(Texture.WMRepeat)
		else:
			self.texture.setWrapU(Texture.WMClamp)
		if repeatY > 1:
			self.texture.setWrapV(Texture.WMRepeat)
		else:
			self.texture.setWrapV(Texture.WMClamp)

		self.node.setTexture(self.texture)
		self.setFrame(0)

	def nextsize(self, num):
		""" Finds the next power of two size for the given integer. """
		p2x=max(1,log(num,2))
		notP2X=modf(p2x)[0]>0
		return 2**int(notP2X+p2x)

	def setFrame(self, frame=0):
		""" Sets the current sprite to the given frame """
		self.frameInterrupt = True # A flag to tell the animation task to shut it up ur face
		self.currentFrame = frame
		self.flipTexture()

	def playAnim(self, animName, loop=False):
		""" Sets the sprite to animate the given named animation. Booleon to loop animation"""
		if not taskMgr.hasTaskNamed("Animate sprite" + self.spriteNum):
			if hasattr(self, "task"):
					taskMgr.remove("Animate sprite" + self.spriteNum)
					del self.task
			self.frameInterrupt = False # Clear any previous interrupt flags
			self.loopAnim = loop
			self.currentAnim = self.animations[animName]
			self.currentAnim.playhead = 0
			self.task = taskMgr.doMethodLater(1.0/self.currentAnim.fps,self.animPlayer, "Animate sprite" + self.spriteNum)

	def createAnim(self, animName, frameCols, fps=12):
		""" Create a named animation. Takes the animation name and a tuple of frame numbers """
		self.animations[animName] = Sprite2d.Animation(frameCols, fps)
		return self.animations[animName]

	def flipX(self, val=None):
		""" Flip the sprite on X. If no value given, it will invert the current flipping."""
		if val:
			self.flip['x'] = val
		else:
			if self.flip['x']:
				self.flip['x'] = False
			else:
				self.flip['x'] = True
		self.flipTexture()
		return self.flip['x']

	def flipY(self, val=None):
		""" See flipX """
		if val:
			self.flip['y'] = val
		else:
			if self.flip['y']:
				self.flip['y'] = False
			else:
				self.flip['y'] = True
		self.flipTexture()
		return self.flip['y']

	def updateCameraAngle(self, cameraNode):
		baseH =  cameraNode.getH(render) - self.node.getH(render)
		degreesBetweenCards = 360/len(self.cards)
		bestCard = int(((baseH)+degreesBetweenCards/2)%360 / degreesBetweenCards)
		#print baseH, bestCard
		for i in range(len(self.cards)):
			if i == bestCard:
				self.cards[i].show()
			else:
				self.cards[i].hide()

	def flipTexture(self):
		""" Sets the texture coordinates of the texture to the current frame"""
		for i in range(len(self.cards)):
			currentRow = self.rowPerFace[i]

			sU = self.offsetX * self.repeatX
			sV = self.offsetY * self.repeatY
			oU = 0 + self.currentFrame * self.uSize
			#oU = 0 + self.frames[self.currentFrame].col * self.uSize
			#oV = 1 - self.frames[self.currentFrame].row * self.vSize - self.offsetY
			oV = 1 - currentRow * self.vSize - self.offsetY
			if self.flip['x'] ^ i==1: ##hack to fix side view
				#print "flipping, i = ",i
				sU *= -1
				#oU = self.uSize + self.frames[self.currentFrame].col * self.uSize
				oU = self.uSize + self.currentFrame * self.uSize
			if self.flip['y']:
				sV *= -1
				#oV = 1 - self.frames[self.currentFrame].row * self.vSize
				oV = 1 - currentRow * self.vSize
			self.cards[i].setTexScale(TextureStage.getDefault(), sU, sV)
			self.cards[i].setTexOffset(TextureStage.getDefault(), oU, oV)

	def clear(self):
		""" Free up the texture memory being used """
		self.texture.clear()
		self.paddedImg.clear()
		self.node.removeNode()

	def animPlayer(self, task):
		if self.frameInterrupt:
			return task.done
		#print "Playing",self.currentAnim.cells[self.currentAnim.playhead]
		self.currentFrame = self.currentAnim.cells[self.currentAnim.playhead]
		self.flipTexture()
		if self.currentAnim.playhead+1 < len(self.currentAnim.cells):
			self.currentAnim.playhead += 1
			return task.again
		if self.loopAnim:
			self.currentAnim.playhead = 0
			return task.again
예제 #52
0
def getBackgroundSet(menuItem, frame, arrowhead):
    item = menuItem.item
    kind = item['kind']
    txt = item['txt']
    grphcs = []
    slctrs = ['menu ' + kind]
    if 'class' in item:  # class after kind: class has higher priority
        slctrs.append('.' + item['class'])
    if 'id' in item:  # id after class: id has higher priority
        slctrs.append('#' + item['id'])
    style = getStyle(slctrs, menuItem.cssFName)
    if 'enter-sound' in style:
        loadSound(menuItem, menuItem.getEnterEvent(), style, 'enter-sound')
    if 'exit-sound' in style:
        loadSound(menuItem, menuItem.getExitEvent(), style, 'exit-sound')
    if 'press-sound' in style:
        loadSound(menuItem, menuItem.getPressEvent(MouseButton.one()), style,
                  'press-sound')
    if 'release-sound' in style:
        loadSound(menuItem, menuItem.getReleaseEvent(MouseButton.one()), style,
                  'release-sound')
    if 'drag-sound' in style: loadSound(menuItem, None, style, 'drag-sound')
    for state in STATES:
        slctrs = ['menu ' + kind + ' :' + stateName[state].lower()]
        if 'class' in item:  # class after kind: class has higher priority
            slctrs.append('.' + item['class'] + ' :' +
                          stateName[state].lower())
        if 'id' in item:  # id after class: id has higher priority
            slctrs.append('#' + item['id'] + ' :' + stateName[state].lower())
        style = getStyle(slctrs, menuItem.cssFName)
        # Want to add more style properties?
        # Do it here:
        # Match style keys here to property names in .ccss
        fontSize = style['font-size']
        bevel = style['bevel'] * fontSize
        font = style['font']
        color = style['color']
        tn = TextNode(txt)
        tn.setText(txt)
        tn.setFont(loader.loadFont(font))
        tn.setSlant(style['slant'])
        tn.setTextColor(color)
        tn.setShadow(*style['shadow-offset'])
        tn.setShadowColor(*style['shadow-color'])
        NodePath(tn).setScale(fontSize)
        sHolder = NodePath(PandaNode('sHolder'))
        sHolder.attachNewNode(tn)
        grphcs.append(sHolder)
        sHolder.attachNewNode(tn)
        borderColor = style['border-Color']
        thk = style['border-thickness']
        if 'background-Color' in style and\
         style['background-Color'] != 'transparent':
            bgColor = style['background-Color']
        else:
            bgColor = None
        if kind == 'parent':
            if state == HOVER: ar = arrowhead * 2
            else: ar = arrowhead
            grphcs[state].attachNewNode(
                bevelArrow(frame, bevel, ar, thk, color, borderColor, bgColor))
        elif kind in ('horizontal', 'titleBar', 'close'):
            grphcs[state].attachNewNode(
                rectangle(frame, thk, color, borderColor, bgColor))
        elif kind == 'checkBox':
            grphcs[state].attachNewNode(
                checkBox(frame, bevel, thk, color, borderColor, bgColor))
            cb = grphcs[state].attachNewNode(
                checkedBox(frame, bevel, thk, color, borderColor, bgColor))
            cb.hide()
        elif kind == 'radioBTN':
            grphcs[state].attachNewNode(
                radioBTN(frame, bevel, thk, color, borderColor, bgColor))
            cb = grphcs[state].attachNewNode(
                checkedRadioBTN(frame, bevel, thk, color, borderColor,
                                bgColor))
            cb.hide()
        else:
            grphcs[state].attachNewNode(
                bevelBG(frame, bevel, thk, borderColor, bgColor))
    return grphcs
예제 #53
0
class CogdoFlyingGuiManager:
    def __init__(self, player):

        self.player = player

        self.root = NodePath("CogdoFlyingGui")
        self.root.reparentTo(aspect2d)

        self.fuelMeter = NodePath("scrubMeter")
        self.fuelMeter.reparentTo(self.root)
        self.fuelMeter.setPos(1.1, 0.0, -0.7)
        self.fuelMeter.setSz(2.0)

        cm = CardMaker('card')
        cm.setFrame(-0.07, 0.07, 0.0, 0.75)
        self.fuelMeterBar = self.fuelMeter.attachNewNode(cm.generate())
        self.fuelMeterBar.setColor(0.95, 0.95, 0.0, 1.0)

        self.fuelLabel = DirectLabel(
            parent=self.root,
            relief=None,
            pos=(1.1, 0, -0.8),
            scale=0.075,
            text="Fuel",
            text_fg=(0.95, 0.95, 0, 1),
            text_shadow=(0, 0, 0, 1),
            text_font=ToontownGlobals.getInterfaceFont(),
        )

        self.messageLabel = DirectLabel(
            parent=self.root,
            relief=None,
            pos=(0.0, 0.0, -0.9),
            scale=0.1,
            text="                ",
            text_align=TextNode.ACenter,
            text_fg=(0.95, 0.95, 0, 1),
            text_shadow=(0, 0, 0, 1),
            text_font=ToontownGlobals.getInterfaceFont(),
            textMayChange=1,
        )
        self.messageLabel.stash()

        self.winLabel = DirectLabel(
            parent=self.root,
            relief=None,
            pos=(0.0, 0.0, 0.0),
            scale=0.25,
            text="You win!",
            text_align=TextNode.ACenter,
            text_fg=(0.95, 0.95, 0, 1),
            text_shadow=(0, 0, 0, 1),
            text_font=ToontownGlobals.getInterfaceFont(),
        )
        self.winLabel.stash()

        self.refuelLerp = LerpFunctionInterval(self.fuelMeterBar.setSz,
                                               fromData=0.0,
                                               toData=1.0,
                                               duration=2.0)

    def setRefuelLerpFromData(self):
        startScale = self.fuelMeterBar.getSz()
        self.refuelLerp.fromData = startScale

    def setMessageLabelText(self, text):
        self.messageLabel["text"] = text
        self.messageLabel.setText()

    def update(self):
        self.fuelMeterBar.setSz(self.player.fuel)

    def destroy(self):
        #        print "Destroying GUI"
        self.fuelMeterBar.detachNode()
        self.fuelMeterBar = None

        self.fuelLabel.detachNode()
        self.fuelLabel = None

        self.fuelMeter.detachNode()
        self.fuelMeter = None

        self.winLabel.detachNode()
        self.winLabel = None

        self.root.detachNode()
        self.root = None

        self.player = None
예제 #54
0
class DistributedPartyActivity(DistributedObject.DistributedObject):
    deferFor = 1

    def __init__(self,
                 cr,
                 activityId,
                 activityType,
                 wantLever=False,
                 wantRewardGui=False):
        DistributedObject.DistributedObject.__init__(self, cr)
        self.activityId = activityId
        self.activityName = PartyGlobals.ActivityIds.getString(self.activityId)
        self.activityType = activityType
        self.wantLever = wantLever
        self.wantRewardGui = wantRewardGui
        self.messageGui = None
        self.rewardGui = None
        self.toonIds = []
        self._toonId2ror = {}
        childName = '%s' % self
        childName = childName[childName.rfind('.DistributedParty') +
                              len('.DistributedParty'):childName.
                              rfind('Activity instance')]
        if not hasattr(base, 'partyActivityDict'):
            base.partyActivityDict = {}
        base.partyActivityDict[childName] = self
        self.root = NodePath('root')
        self.rulesDoneEvent = 'rulesDone'
        self.modelCount = 500
        self.cleanupActions = []
        self.usesSmoothing = 0
        self.usesLookAround = 0
        self.difficultyOverride = None
        self.trolleyZoneOverride = None
        self._localToonRequestStatus = None
        #self.root.setPos(self.x, self.y, self.z)
        return

    def localToonExiting(self):
        self._localToonRequestStatus = PartyGlobals.ActivityRequestStatus.Exiting

    def localToonJoining(self):
        self._localToonRequestStatus = PartyGlobals.ActivityRequestStatus.Joining

    def d_toonJoinRequest(self):
        if self._localToonRequestStatus is None:
            self.localToonJoining()
            self.sendUpdate('toonJoinRequest')
        return

    def d_toonExitRequest(self):
        if self._localToonRequestStatus is None:
            self.localToonExiting()
            self.sendUpdate('toonExitRequest')
        return

    def d_toonExitDemand(self):
        self.localToonExiting()
        self.sendUpdate('toonExitDemand')

    def joinRequestDenied(self, reason):
        self._localToonRequestStatus = None
        return

    def exitRequestDenied(self, reason):
        self._localToonRequestStatus = None
        return

    def handleToonJoined(self, toonId):
        self.notify.error('BASE: handleToonJoined should be overridden %s' %
                          self.activityName)

    def handleToonExited(self, toonId):
        self.notify.error('BASE: handleToonExited should be overridden %s' %
                          self.activityName)

    def handleToonDisabled(self, toonId):
        self.notify.error('BASE: handleToonDisabled should be overridden %s' %
                          self.activityName)

    def setToonsPlaying(self, toonIds):
        exitedToons, joinedToons = self.getToonsPlayingChanges(
            self.toonIds, toonIds)
        self.setToonIds(toonIds)
        self._processExitedToons(exitedToons)
        self._processJoinedToons(joinedToons)

    def _processExitedToons(self, exitedToons):
        for toonId in exitedToons:
            if toonId != base.localAvatar.doId or toonId == base.localAvatar.doId and self.isLocalToonRequestStatus(
                    PartyGlobals.ActivityRequestStatus.Exiting):
                toon = self.getAvatar(toonId)
                if toon is not None:
                    self.ignore(toon.uniqueName('disable'))
                self.handleToonExited(toonId)
                if toonId == base.localAvatar.doId:
                    self._localToonRequestStatus = None
                if toonId in self._toonId2ror:
                    self.cr.relatedObjectMgr.abortRequest(
                        self._toonId2ror[toonId])
                    del self._toonId2ror[toonId]

        return

    def _processJoinedToons(self, joinedToons):
        for toonId in joinedToons:
            if toonId != base.localAvatar.doId or toonId == base.localAvatar.doId and self.isLocalToonRequestStatus(
                    PartyGlobals.ActivityRequestStatus.Joining):
                if toonId not in self._toonId2ror:
                    request = self.cr.relatedObjectMgr.requestObjects(
                        [toonId], allCallback=self._handlePlayerPresent)
                    if toonId in self._toonId2ror:
                        del self._toonId2ror[toonId]
                    else:
                        self._toonId2ror[toonId] = request

    def _handlePlayerPresent(self, toons):
        toon = toons[0]
        toonId = toon.doId
        if toonId in self._toonId2ror:
            del self._toonId2ror[toonId]
        else:
            self._toonId2ror[toonId] = None
        self._enableHandleToonDisabled(toonId)
        self.handleToonJoined(toonId)
        if toonId == base.localAvatar.doId:
            self._localToonRequestStatus = None
        return

    def _enableHandleToonDisabled(self, toonId):
        toon = self.getAvatar(toonId)
        if toon is not None:
            self.acceptOnce(toon.uniqueName('disable'),
                            self.handleToonDisabled, [toonId])
        else:
            self.notify.warning(
                'BASE: unable to get handle to toon with toonId:%d. Hook for handleToonDisabled not set.'
                % toonId)
        return

    def isLocalToonRequestStatus(self, requestStatus):
        return self._localToonRequestStatus == requestStatus

    def setToonIds(self, toonIds):
        self.toonIds = toonIds

    def getToonsPlayingChanges(self, oldToonIds, newToonIds):
        oldToons = set(oldToonIds)
        newToons = set(newToonIds)
        exitedToons = oldToons.difference(newToons)
        joinedToons = newToons.difference(oldToons)
        return (list(exitedToons), list(joinedToons))

    def setUsesSmoothing(self):
        self.usesSmoothing = True

    def setUsesLookAround(self):
        self.usesLookAround = True

    def getInstructions(self):
        return TTLocalizer.DefaultPartyActivityInstructions

    def getParentNodePath(self):
        if hasattr(base.cr.playGame,
                   'hood') and base.cr.playGame.hood and hasattr(
                       base.cr.playGame.hood,
                       'loader') and base.cr.playGame.hood.loader and hasattr(
                           base.cr.playGame.hood.loader,
                           'geom') and base.cr.playGame.hood.loader.geom:
            return base.cr.playGame.hood.loader.geom
        else:
            self.notify.warning(
                'Hood or loader not created, defaulting to render')
            return render

    def __createRandomNumGen(self):
        self.notify.debug('BASE: self.doId=0x%08X' % self.doId)
        self.randomNumGen = RandomNumGen.RandomNumGen(self.doId)

        def destroy(self=self):
            self.notify.debug('BASE: destroying random num gen')
            del self.randomNumGen

        self.cleanupActions.append(destroy)

    def generate(self):
        DistributedObject.DistributedObject.generate(self)
        self.notify.debug('BASE: generate, %s' % self.getTitle())
        self.__createRandomNumGen()

    def announceGenerate(self):
        DistributedObject.DistributedObject.announceGenerate(self)
        self.notify.debug('BASE: announceGenerate %s' % self.activityName)
        self.root.setName(self.activityName + 'Root')
        centeredX, centeredY = getCenterPosFromGridSize(
            self.x, self.y,
            PartyGlobals.ActivityInformationDict[self.activityId]['gridsize'])
        self.root.setPos(centeredX, centeredY, 0.0)
        self.root.setH(self.h)
        self.root.setZ(self.z)
        self.normalExit = True
        if self.wantLever:
            self.leverTriggerEvent = self.uniqueName('leverTriggerEvent')
        self.load()

        def cleanup(self=self):
            self.notify.debug('BASE: cleanup: normalExit=%s' % self.normalExit)
            base.cr.renderFrame()
            if self.normalExit:
                self.sendUpdate('toonExitRequest')

        self.cleanupActions.append(cleanup)

    def disable(self):
        self.notify.debug('BASE: disable')
        DistributedObject.DistributedObject.disable(self)
        rorToonIds = self._toonId2ror.keys()
        for toonId in rorToonIds:
            self.cr.relatedObjectMgr.abortRequest(self._toonId2ror[toonId])
            del self._toonId2ror[toonId]

        self.ignore(self.messageDoneEvent)
        if self.messageGui is not None and not self.messageGui.isEmpty():
            self.messageGui.cleanup()
            self.messageGui = None
        return

    def delete(self):
        self.notify.debug('BASE: delete')
        self.unload()
        self.ignoreAll()
        DistributedObject.DistributedObject.delete(self)

    def load(self):
        self.notify.debug('BASE: load')
        self.loadSign()
        if self.wantLever:
            self.loadLever()
        if self.wantRewardGui:
            self.showRewardDoneEvent = self.uniqueName('showRewardDoneEvent')
            self.rewardGui = JellybeanRewardGui(self.showRewardDoneEvent)
        self.messageDoneEvent = self.uniqueName('messageDoneEvent')
        self.root.reparentTo(self.getParentNodePath())
        self._enableCollisions()

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

    def loadLever(self):
        self.lever = self.root.attachNewNode('%sLever' % self.activityName)
        self.leverModel = self.party.defaultLeverModel.copyTo(self.lever)
        self.controlColumn = NodePath('cc')
        column = self.leverModel.find('**/column')
        column.getChildren().reparentTo(self.controlColumn)
        self.controlColumn.reparentTo(column)
        self.stickHinge = self.controlColumn.attachNewNode('stickHinge')
        self.stick = self.party.defaultStickModel.copyTo(self.stickHinge)
        self.stickHinge.setHpr(0.0, 90.0, 0.0)
        self.stick.setHpr(0, -90.0, 0)
        self.stick.flattenLight()
        self.bottom = self.leverModel.find('**/bottom')
        self.bottom.wrtReparentTo(self.controlColumn)
        self.bottomPos = self.bottom.getPos()
        cs = CollisionSphere(0.0, 1.35, 2.0, 1.0)
        cs.setTangible(False)
        cn = CollisionNode(self.leverTriggerEvent)
        cn.addSolid(cs)
        cn.setIntoCollideMask(OTPGlobals.WallBitmask)
        self.leverTrigger = self.root.attachNewNode(cn)
        self.leverTrigger.reparentTo(self.lever)
        self.leverTrigger.stash()
        cs = CollisionTube(0.0, 2.7, 0.0, 0.0, 2.7, 3.0, 1.2)
        cn = CollisionNode('levertube')
        cn.addSolid(cs)
        cn.setIntoCollideMask(OTPGlobals.WallBitmask)
        self.leverTube = self.leverModel.attachNewNode(cn)
        host = base.cr.doId2do.get(self.party.partyInfo.hostId)
        if host is None:
            self.notify.debug(
                '%s loadLever : Host has left the game before lever could be created.'
                % self.activityName)
            return
        scale = host.getGeomNode().getChild(0).getSz(render)
        self.leverModel.setScale(scale)
        self.controlColumn.setPos(0, 0, 0)
        host.setPosHpr(self.lever, 0, 0, 0, 0, 0, 0)
        host.pose('leverNeutral', 0)
        host.update()
        pos = host.rightHand.getPos(self.controlColumn)
        self.controlColumn.setPos(pos[0], pos[1], pos[2] - 1)
        self.bottom.setZ(host, 0.0)
        self.bottom.setPos(self.bottomPos[0], self.bottomPos[1],
                           self.bottom.getZ())
        lookAtPoint = Point3(0.3, 0, 0.1)
        lookAtUp = Vec3(0, -1, 0)
        self.stickHinge.lookAt(host.rightHand, lookAtPoint, lookAtUp)
        host.play('walk')
        host.update()
        return

    def unloadLever(self):
        self.lever.removeNode()
        self.leverModel.removeNode()
        self.controlColumn.removeNode()
        self.stickHinge.removeNode()
        self.stick.removeNode()
        self.bottom.removeNode()
        self.leverTrigger.removeNode()
        self.leverTube.removeNode()
        del self.bottomPos
        del self.lever
        del self.leverModel
        del self.controlColumn
        del self.stickHinge
        del self.stick
        del self.bottom
        del self.leverTrigger
        del self.leverTube

    def _enableCollisions(self):
        if self.wantLever:
            self.leverTrigger.unstash()
            self.accept('enter%s' % self.leverTriggerEvent, self._leverPulled)

    def _disableCollisions(self):
        if self.wantLever:
            self.leverTrigger.stash()
            self.ignore('enter%s' % self.leverTriggerEvent)

    def _leverPulled(self, collEntry):
        self.notify.debug('_leverPulled : Someone pulled the lever!!! ')
        if self.activityType == PartyGlobals.ActivityTypes.HostInitiated and base.localAvatar.doId != self.party.partyInfo.hostId:
            return False
        return True

    def getToonPullingLeverInterval(self, toon):
        walkTime = 0.2
        reach = ActorInterval(toon, 'leverReach', playRate=2.0)
        pull = ActorInterval(toon, 'leverPull', startFrame=6)
        origPos = toon.getPos(render)
        origHpr = toon.getHpr(render)
        newPos = self.lever.getPos(render)
        newHpr = self.lever.getHpr(render)
        origHpr.setX(PythonUtil.fitSrcAngle2Dest(origHpr[0], newHpr[0]))
        toon.setPosHpr(origPos, origHpr)
        reachAndPull = Sequence(
            ActorInterval(toon,
                          'walk',
                          loop=True,
                          duration=walkTime - reach.getDuration()), reach,
            pull)
        leverSeq = Sequence(
            Wait(walkTime + reach.getDuration() - 0.1),
            self.stick.hprInterval(0.55, Point3(0.0, 25.0, 0.0),
                                   Point3(0.0, 0.0, 0.0)), Wait(0.3),
            self.stick.hprInterval(0.4, Point3(0.0, 0.0, 0.0),
                                   Point3(0.0, 25.0, 0.0)))
        returnSeq = Sequence(
            Parallel(toon.posInterval(walkTime, newPos, origPos),
                     toon.hprInterval(walkTime, newHpr, origHpr), leverSeq,
                     reachAndPull))
        return returnSeq

    def showMessage(self, message, endState='walk'):
        base.cr.playGame.getPlace().fsm.request('activity')
        self.acceptOnce(self.messageDoneEvent, self.__handleMessageDone)
        self.messageGui = TTDialog.TTGlobalDialog(
            doneEvent=self.messageDoneEvent,
            message=message,
            style=TTDialog.Acknowledge)
        self.messageGui.endState = endState

    def __handleMessageDone(self):
        self.ignore(self.messageDoneEvent)
        if hasattr(base.cr.playGame.getPlace(), 'fsm'):
            if self.messageGui and hasattr(self.messageGui, 'endState'):
                self.notify.info('__handleMessageDone (endState=%s)' %
                                 self.messageGui.endState)
                base.cr.playGame.getPlace().fsm.request(
                    self.messageGui.endState)
            else:
                self.notify.warning(
                    "messageGui has no endState, defaulting to 'walk'")
                base.cr.playGame.getPlace().fsm.request('walk')
        if self.messageGui is not None and not self.messageGui.isEmpty():
            self.messageGui.cleanup()
            self.messageGui = None
        return

    def showJellybeanReward(self, earnedAmount, jarAmount, message):
        if not self.isLocalToonInActivity(
        ) or base.localAvatar.doId in self.getToonIdsAsList():
            messenger.send('DistributedPartyActivity-showJellybeanReward')
            base.cr.playGame.getPlace().fsm.request('activity')
            self.acceptOnce(self.showRewardDoneEvent,
                            self.__handleJellybeanRewardDone)
            self.rewardGui.showReward(earnedAmount, jarAmount, message)

    def __handleJellybeanRewardDone(self):
        self.ignore(self.showRewardDoneEvent)
        self.handleRewardDone()

    def handleRewardDone(self):
        if base.cr.playGame.getPlace() and hasattr(base.cr.playGame.getPlace(),
                                                   'fsm'):
            base.cr.playGame.getPlace().fsm.request('walk')

    def setSignNote(self, note):
        self.noteText.node().setText(note)
        if len(note.strip()) > 0:
            self.signFlat.stash()
            self.signFlatWithNote.unstash()
            self.signTextLocator.unstash()
        else:
            self.signFlat.unstash()
            self.signFlatWithNote.stash()
            self.signTextLocator.stash()

    def unload(self):
        self.notify.debug('BASE: unload')
        self.finishRules()
        self._disableCollisions()
        self.signModel.removeNode()
        del self.signModel
        self.sign.removeNode()
        del self.sign
        self.ignoreAll()
        if self.wantLever:
            self.unloadLever()
        self.root.removeNode()
        del self.root
        del self.activityId
        del self.activityName
        del self.activityType
        del self.wantLever
        del self.messageGui
        if self.rewardGui is not None:
            self.rewardGui.destroy()
        del self.rewardGui
        if hasattr(self, 'toonIds'):
            del self.toonIds
        del self.rulesDoneEvent
        del self.modelCount
        del self.cleanupActions
        del self.usesSmoothing
        del self.usesLookAround
        del self.difficultyOverride
        del self.trolleyZoneOverride
        if hasattr(base, 'partyActivityDict'):
            del base.partyActivityDict
        return

    def setPartyDoId(self, partyDoId):
        #print base.cr.doId2do
        self.party = base.cr.doId2do[partyDoId]

    def setX(self, x):
        self.x = x

    def setY(self, y):
        self.y = y

    def setZ(self, z):
        self.z = z

    def setH(self, h):
        self.h = h

    def setState(self, newState, timestamp):
        if newState == 'Active':
            self.activityStartTime = globalClockDelta.networkToLocalTime(
                timestamp)

    def turnOffSmoothingOnGuests(self):
        for toonId in self.toonIds:
            avatar = self.getAvatar(toonId)
            if avatar:
                if not self.usesSmoothing:
                    avatar.stopSmooth()
                if not self.usesLookAround:
                    avatar.stopLookAround()

    def getAvatar(self, toonId):
        if self.cr.doId2do.has_key(toonId):
            return self.cr.doId2do[toonId]
        else:
            self.notify.warning(
                'BASE: getAvatar: No avatar in doId2do with id: ' +
                str(toonId))
            return None
        return None

    def getAvatarName(self, toonId):
        avatar = self.getAvatar(toonId)
        if avatar:
            return avatar.getName()
        else:
            return 'Unknown'

    def isLocalToonInActivity(self):
        result = False
        place = base.cr.playGame.getPlace()
        if place and place.__class__.__name__ == 'Party' and hasattr(
                place, 'fsm') and place.fsm:
            result = place.fsm.getCurrentState().getName() == 'activity'
        return result

    def getToonIdsAsList(self):
        return self.toonIds

    def startRules(self, timeout=PartyGlobals.DefaultRulesTimeout):
        self.notify.debug('BASE: startRules')
        self.accept(self.rulesDoneEvent, self.handleRulesDone)
        self.rulesPanel = MinigameRulesPanel('PartyRulesPanel',
                                             self.getTitle(),
                                             self.getInstructions(),
                                             self.rulesDoneEvent, timeout)
        base.setCellsAvailable(
            base.bottomCells + [base.leftCells[0], base.rightCells[1]], False)
        self.rulesPanel.load()
        self.rulesPanel.enter()

    def finishRules(self):
        self.notify.debug('BASE: finishRules')
        self.ignore(self.rulesDoneEvent)
        if hasattr(self, 'rulesPanel'):
            self.rulesPanel.exit()
            self.rulesPanel.unload()
            del self.rulesPanel
            base.setCellsAvailable(
                base.bottomCells + [base.leftCells[0], base.rightCells[1]],
                True)

    def handleRulesDone(self):
        self.notify.error('BASE: handleRulesDone should be overridden')

    def getTitle(self):
        return TTLocalizer.PartyActivityNameDict[self.activityId]['generic']

    def local2ActivityTime(self, timestamp):
        return timestamp - self.activityStartTime

    def activity2LocalTime(self, timestamp):
        return timestamp + self.activityStartTime

    def getCurrentActivityTime(self):
        return self.local2ActivityTime(globalClock.getFrameTime())

    def disableEmotes(self):
        Emote.globalEmote.disableAll(base.localAvatar)

    def enableEmotes(self):
        Emote.globalEmote.releaseAll(base.localAvatar)
예제 #55
0
    def UpdateCollisionAndGeom(self, geom, blocks, x, y, z):
        """ Creates the visible Geometry for the block as well as 
        its Collision Geometry. Returns the geometry data.
        
        @param geom:       The empty dict for the geometry data
        @param blocks:     The 3D array of Block objects for the environment
        @param x, y, z:    The starting coordinates of this geometry in global space
        """ 
        
        # Remove the old collision geometries (since we're updating, chances
        # are that they have changed)
        if(self.wallCollisionGeom):
            self.wallCollisionGeom.removeNode()
        if(self.floorCollisionGeom):
            self.floorCollisionGeom.removeNode()
            
        # Create the new wall and floor geometries
        wallCollisionGeom = NodePath('wallCollisionGeom') 
        wallCollisionGeom.reparentTo(render)
        floorCollisionGeom = NodePath('floorCollisionGeom') 
        floorCollisionGeom.reparentTo(render)
        
        # For each bock, if the block has geometry,
        # add it to the chunks geometry
        for x1 in xrange(ChunkOfBlocks.CHUNK_SIZE): 
            for y1 in xrange(ChunkOfBlocks.CHUNK_SIZE):
                for z1 in xrange(ChunkOfBlocks.CHUNK_SIZE):
                    
                    x2 = x * ChunkOfBlocks.CHUNK_SIZE + x1
                    y2 = y * ChunkOfBlocks.CHUNK_SIZE + y1
                    z2 = z * ChunkOfBlocks.CHUNK_SIZE + z1
                    
                    b = blocks[x2][y2][z2]
                    
                    # Look to adjacent blocks to figure out which BlockFaces of the current
                    # block need to be rendered
                    if(b.IsSolid()):
                        facesToDraw = []
                        for blockSide in xrange(6):
                            adjacent = self.environment.GetAdjacentBlock(x2, y2, z2, blockSide)
                            if(not adjacent.IsSolid()):         # If any blockfaces are adjacent to air, 
                                facesToDraw.append(blockSide)   # they need to be drawn
                                
                        # Create the visible geometry and the collision geometry for each face of this block
                        geomFaces = self.geomGen.GenerateBlockGeometry(x2, y2, z2, b, facesToDraw)
                        collisionFaces = BlockCollisionGeometryGenerator.GenerateCollisionGeometry(geomFaces)
                        
                        # For every drawn face of the block, we need to contain all of
                        # geometry data in a primitive
                        for k in xrange(len(geomFaces)):
                            geomFace = geomFaces[k]
                            
                            # For every vertex on a face, add the data to the geom dict             
                            for index in xrange(0, len(geomFace.vertex)):
                                geom['vertex'].addData3f(geomFace.vertex[index])
                                geom['texcoord'].addData2f(geomFace.texcoord[index])
                                #geom['lighttex'].addData2f(geomFace.lighttex[index])
                                geom['normal'].addData3f(geomFace.normal[index])
                            
                            i = geom['index'] 
                            d = i * (3 + 1) 
                            geom['prim'].addVertices(d, d + 2, d + 1) 
                            geom['prim'].addVertices(d, d + 3, d + 2) 
                            geom['index'] += 1 
                            
                            # FIX ME - K DOES NOT CORRESPOND DIRECTLY TO THE BLOCK FACE
#                            if(k == BlockFace.TOP or k == BlockFace.BOTTOM):
#                                floorCollisionGeom.attachNewNode(collisionFaces[k])
#                            else:
#                                wallCollisionGeom.attachNewNode(collisionFaces[k])
                            
                            wallCollisionGeom.attachNewNode(collisionFaces[k])
                            
                            NodePath(collisionFaces[k]).setPythonTag(Globals.TAG_COLLISION, Globals.COLLISION_BLOCK)
                            NodePath(collisionFaces[k]).setPythonTag(Globals.TAG_BLOCK, b)
                            
        # Close the geometry and add it to the node
        geom['prim'].closePrimitive() 
        geom['geom'].addPrimitive(geom['prim']) 
        self.floorCollisionGeom = floorCollisionGeom
        self.wallCollisionGeom = wallCollisionGeom
        
        return geom
예제 #56
0
class PartyCog(FSM):
    notify = directNotify.newCategory('PartyCog')
    HpTextGenerator = TextNode('HpTextGenerator')
    hpText = None
    height = 7

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

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

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

    def enterStatic(self):
        pass

    def exitStatic(self):
        pass

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def showHitScore(self, number, scale=1):
        if number <= 0:
            return
        if self.hpText:
            self.hideHitScore()
        self.HpTextGenerator.setFont(ToontownGlobals.getSignFont())
        if number < 0:
            self.HpTextGenerator.setText(str(number))
        else:
            self.HpTextGenerator.setText('+' + str(number))
        self.HpTextGenerator.clearShadow()
        self.HpTextGenerator.setAlign(TextNode.ACenter)
        r = 1
        g = 1
        b = 0
        a = 1
        self.HpTextGenerator.setTextColor(r, g, b, a)
        self.hpTextNode = self.HpTextGenerator.generate()
        self.hpText = render.attachNewNode(self.hpTextNode)
        self.hpText.setScale(scale)
        self.hpText.setBillboardPointEye()
        self.hpText.setBin('fixed', 100)
        self.hpText.setPos(self.root, 0, 0, self.height / 2)
        seq = Task.sequence(
            self.hpText.lerpPos(Point3(
                self.root.getX(render), self.root.getY(render),
                self.root.getZ(render) + self.height + 1.0),
                                0.25,
                                blendType='easeOut'), Task.pause(0.25),
            self.hpText.lerpColor(Vec4(r, g, b, a), Vec4(r, g, b, 0), 0.1),
            Task.Task(self.__hideHitScoreTask))
        taskMgr.add(seq, 'PartyCogHpText' + str(self.id))

    def __hideHitScoreTask(self, task):
        self.hideHitScore()
        return Task.done

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

    def getHeadLocation(self):
        self.actor.getJoints(jointName='head')[0].getNetTransform(
            self.temp_transform)
        self.head_locator.setMat(self.temp_transform)
        return self.head_locator.getZ(self.root)
예제 #57
0
    def renderSceneInto(self, depthtex=None, colortex=None, auxtex=None, auxbits=0, textures=None):

        """ Causes the scene to be rendered into the supplied textures
        instead of into the original window.  Puts a fullscreen quad
        into the original window to show the render-to-texture results.
        Returns the quad.  Normally, the caller would then apply a
        shader to the quad.

        To elaborate on how this all works:

        * An offscreen buffer is created.  It is set up to mimic
          the original display region - it is the same size,
          uses the same clear colors, and contains a DisplayRegion
          that uses the original camera.

        * A fullscreen quad and an orthographic camera to render
          that quad are both created.  The original camera is
          removed from the original window, and in its place, the
          orthographic quad-camera is installed.

        * The fullscreen quad is textured with the data from the
          offscreen buffer.  A shader is applied that tints the
          results pink.

        * Automatic shader generation NOT enabled.
          If you have a filter that depends on a render target from
          the auto-shader, you either need to set an auto-shader
          attrib on the main camera or scene, or, you need to provide
          these outputs in your own shader.

        * All clears are disabled on the original display region.
          If the display region fills the whole window, then clears
          are disabled on the original window as well.  It is
          assumed that rendering the full-screen quad eliminates
          the need to do clears.

        Hence, the original window which used to contain the actual
        scene, now contains a pink-tinted quad with a texture of the
        scene.  It is assumed that the user will replace the shader
        on the quad with a more interesting filter. """

        if (textures):
            colortex = textures.get("color", None)
            depthtex = textures.get("depth", None)
            auxtex = textures.get("aux", None)
            auxtex0 = textures.get("aux0", auxtex)
            auxtex1 = textures.get("aux1", None)
        else:
            auxtex0 = auxtex
            auxtex1 = None

        if (colortex == None):
            colortex = Texture("filter-base-color")
            colortex.setWrapU(Texture.WMClamp)
            colortex.setWrapV(Texture.WMClamp)

        texgroup = (depthtex, colortex, auxtex0, auxtex1)

        # Choose the size of the offscreen buffer.

        (winx, winy) = self.getScaledSize(1,1,1)
        buffer = self.createBuffer("filter-base", winx, winy, texgroup)

        if (buffer == None):
            return None

        cm = CardMaker("filter-base-quad")
        cm.setFrameFullscreenQuad()
        quad = NodePath(cm.generate())
        quad.setDepthTest(0)
        quad.setDepthWrite(0)
        quad.setTexture(colortex)
        quad.setColor(Vec4(1,0.5,0.5,1))

        cs = NodePath("dummy")
        cs.setState(self.camstate)
        # Do we really need to turn on the Shader Generator?
        #cs.setShaderAuto()
        if (auxbits):
            cs.setAttrib(AuxBitplaneAttrib.make(auxbits))
        self.camera.node().setInitialState(cs.getState())

        quadcamnode = Camera("filter-quad-cam")
        lens = OrthographicLens()
        lens.setFilmSize(2, 2)
        lens.setFilmOffset(0, 0)
        lens.setNearFar(-1000, 1000)
        quadcamnode.setLens(lens)
        quadcam = quad.attachNewNode(quadcamnode)
        
        self.region.setCamera(quadcam)

        self.setStackedClears(buffer, self.rclears, self.wclears)
        if (auxtex0):
            buffer.setClearActive(GraphicsOutput.RTPAuxRgba0, 1)
            buffer.setClearValue(GraphicsOutput.RTPAuxRgba0, Vec4(0.5, 0.5, 1.0, 0.0))
        if (auxtex1):
            buffer.setClearActive(GraphicsOutput.RTPAuxRgba1, 1)
        self.region.disableClears()
        if (self.isFullscreen()):
            self.win.disableClears()

        dr = buffer.makeDisplayRegion()
        dr.disableClears()
        dr.setCamera(self.camera)
        dr.setActive(1)

        self.buffers.append(buffer)
        self.sizes.append((1, 1, 1))

        return quad
예제 #58
0
class CogdoFlyingLevel(DirectObject):
    notify = directNotify.newCategory('CogdoFlyingLevel')

    def __init__(self, parent, frameModel, startPlatformModel,
                 endPlatformModel, quadLengthUnits, quadVisibilityAhead,
                 quadVisibiltyBehind):
        self.parent = parent
        self.quadLengthUnits = quadLengthUnits
        self._halfQuadLengthUnits = quadLengthUnits / 2.0
        self.quadVisibiltyAhead = quadVisibilityAhead
        self.quadVisibiltyBehind = quadVisibiltyBehind
        self._frameModel = frameModel
        self.root = NodePath('CogdoFlyingLevel')
        self.quadrantRoot = NodePath('QuadrantsRoot')
        self.quadrantRoot.reparentTo(self.root)
        self._startPlatformModel = startPlatformModel
        self._startPlatformModel.reparentTo(self.root)
        self._startPlatformModel.setZ(Globals.Level.StartPlatformHeight)
        self._endPlatformModel = endPlatformModel
        self._endPlatformModel.reparentTo(self.root)
        self._endPlatformModel.setZ(Globals.Level.EndPlatformHeight)
        self.wallR = self._frameModel.find('**/wallR')
        self.wallL = self._frameModel.find('**/wallL')
        self._exit = CogdoGameExit()
        self._exit.reparentTo(self._endPlatformModel)
        loc = self._endPlatformModel.find('**/exit_loc')
        offset = loc.getPos(render)
        self._exit.setPos(render, offset)
        self.quadrants = []
        self.visibleQuadIndices = []
        self._numQuads = 0
        self._currentQuadNum = -1
        self._camera = None
        self._initCollisions()
        self.upLimit = self._frameModel.find('**/limit_up').getZ(render)
        self.downLimit = self._frameModel.find('**/limit_down').getZ(render)
        self.leftLimit = self._frameModel.find('**/limit_left').getX(
            render) - 30.0
        self.rightLimit = self._frameModel.find('**/limit_right').getX(
            render) + 30.0
        self.backLimit = -self.quadLengthUnits
        self.forwardLimit = self.quadLengthUnits * 20
        self._frameModel.flattenStrong()
        self.gatherableFactory = CogdoFlyingGatherableFactory()
        self.obstacleFactory = CogdoFlyingObtacleFactory()
        return

    def getExit(self):
        return self._exit

    def getBounds(self):
        return ((self.leftLimit, self.rightLimit),
                (self.backLimit, self.forwardLimit), (self.downLimit,
                                                      self.upLimit))

    def getGatherable(self, serialNum):
        for quadrant in self.quadrants:
            for gatherable in quadrant.gatherables:
                if gatherable.serialNum == serialNum:
                    return gatherable

        return None

    def ready(self):
        self.gatherableFactory.destroy()
        del self.gatherableFactory
        self.obstacleFactory.destroy()
        del self.obstacleFactory
        self._initStartEndPlatforms()
        self._frameModel.reparentTo(self.root)
        self.root.reparentTo(self.parent)
        self.root.stash()

    def _initStartEndPlatforms(self):
        self.startPlatform = CogdoFlyingPlatform(
            self._startPlatformModel,
            Globals.Level.PlatformTypes.StartPlatform)
        self.endPlatform = CogdoFlyingPlatform(
            self._endPlatformModel, Globals.Level.PlatformTypes.EndPlatform)
        self._endPlatformModel.setY(self.convertQuadNumToY(self._numQuads))
        self.backLimit = self._startPlatformModel.getY(
            render) - Globals.Level.StartPlatformLength * 0.7
        self.forwardLimit = self._endPlatformModel.getY(
            render) + Globals.Level.EndPlatformLength * 0.7

    def _initCollisions(self):
        self.collPlane = CollisionPlane(
            Plane(Vec3(0, 0, 1.0), Point3(0, 0, 10)))
        self.collPlane.setTangible(0)
        self.collNode = CollisionNode('fogPlane')
        self.collNode.setIntoCollideMask(OTPGlobals.FloorBitmask)
        self.collNode.addSolid(self.collPlane)
        self.collNodePath = self.root.attachNewNode(self.collNode)
        self.collNodePath.hide()

    def destroy(self):
        del self.collPlane
        self.collNodePath.removeNode()
        del self.collNodePath
        del self.collNode
        for quadrant in self.quadrants:
            quadrant.destroy()

        self._exit.destroy()
        del self._exit
        self.root.removeNode()
        del self.root

    def onstage(self):
        self.root.unstash()
        self.update(0.0)

    def offstage(self):
        self.root.stash()

    def start(self, startTime=0.0):
        self._startTime = startTime

    def stop(self):
        pass

    def getLength(self):
        return self.quadLengthUnits * self.getNumQuadrants()

    def appendQuadrant(self, model):
        quadrant = CogdoFlyingLevelQuadrant(self._numQuads, model, self,
                                            self.root)
        if self._numQuads == 0:
            quadrant.generateGatherables(self._startPlatformModel)
        quadrant.offstage()
        self.quadrants.append(quadrant)
        self._numQuads = len(self.quadrants)

    def getNumQuadrants(self):
        return self._numQuads

    def setCamera(self, camera):
        self._camera = camera

    def getCameraActualQuadrant(self):
        camY = self._camera.getY(render)
        y = self.root.getY(render)
        return self.convertYToQuadNum(camY - y)

    def update(self, dt=0.0):
        if self._camera is None:
            return
        quadNum = clamp(self.getCameraActualQuadrant(), 0, self._numQuads - 1)
        if quadNum < self._numQuads:
            self.quadrants[quadNum].update(dt)
            if quadNum + 1 < self._numQuads:
                self.quadrants[quadNum + 1].update(dt)
            if quadNum != self._currentQuadNum:
                self._switchToQuadrant(quadNum)
        return

    def _switchToQuadrant(self, quadNum):
        self.visibleQuadIndices = []
        if quadNum >= 0:
            if quadNum > 0:
                self.quadrants[max(quadNum - self.quadVisibiltyBehind,
                                   0)].onstage()
            for i in range(
                    quadNum,
                    min(quadNum + self.quadVisibiltyAhead + 1,
                        self._numQuads)):
                self.quadrants[i].onstage()
                self.visibleQuadIndices.append(i)
                if i == 0:
                    self.startPlatform.onstage()
                elif i == self._numQuads - 1:
                    self.endPlatform.onstage()

        self._currentQuadNum = quadNum
        for i in range(
                0, max(
                    self._currentQuadNum - self.quadVisibiltyBehind,
                    0)) + range(
                        min(self._currentQuadNum + self.quadVisibiltyAhead + 1,
                            self._numQuads), self._numQuads):
            self.quadrants[i].offstage()
            if i == 0:
                self.startPlatform.offstage()
            elif i == self._numQuads - 1:
                self.endPlatform.offstage()

    def convertQuadNumToY(self, quadNum):
        return quadNum * self.quadLengthUnits

    def convertYToQuadNum(self, y):
        return int(y / self.quadLengthUnits)

    def convertCenterYToQuadNum(self, y):
        return self.convertYToQuadNum(y + self._halfQuadLengthUnits)
예제 #59
0
    def renderSceneInto(self, depthtex=None, colortex=None, auxtex=None, auxbits=0, textures=None):

        """ Causes the scene to be rendered into the supplied textures
        instead of into the original window.  Puts a fullscreen quad
        into the original window to show the render-to-texture results.
        Returns the quad.  Normally, the caller would then apply a
        shader to the quad.

        To elaborate on how this all works:

        * An offscreen buffer is created.  It is set up to mimic
          the original display region - it is the same size,
          uses the same clear colors, and contains a DisplayRegion
          that uses the original camera.

        * A fullscreen quad and an orthographic camera to render
          that quad are both created.  The original camera is
          removed from the original window, and in its place, the
          orthographic quad-camera is installed.

        * The fullscreen quad is textured with the data from the
          offscreen buffer.  A shader is applied that tints the
          results pink.

        * Automatic shader generation NOT enabled.
          If you have a filter that depends on a render target from
          the auto-shader, you either need to set an auto-shader
          attrib on the main camera or scene, or, you need to provide
          these outputs in your own shader.

        * All clears are disabled on the original display region.
          If the display region fills the whole window, then clears
          are disabled on the original window as well.  It is
          assumed that rendering the full-screen quad eliminates
          the need to do clears.

        Hence, the original window which used to contain the actual
        scene, now contains a pink-tinted quad with a texture of the
        scene.  It is assumed that the user will replace the shader
        on the quad with a more interesting filter. """

        if (textures):
            colortex = textures.get("color", None)
            depthtex = textures.get("depth", None)
            auxtex = textures.get("aux", None)

        if (colortex == None):
            colortex = Texture("filter-base-color")
            colortex.setWrapU(Texture.WMClamp)
            colortex.setWrapV(Texture.WMClamp)

        texgroup = (depthtex, colortex, auxtex, None)

        # Choose the size of the offscreen buffer.

        (winx, winy) = self.getScaledSize(1,1,1)
        buffer = self.createBuffer("filter-base", winx, winy, texgroup)

        if (buffer == None):
            return None

        cm = CardMaker("filter-base-quad")
        cm.setFrameFullscreenQuad()
        quad = NodePath(cm.generate())
        quad.setDepthTest(0)
        quad.setDepthWrite(0)
        quad.setTexture(colortex)
        quad.setColor(Vec4(1,0.5,0.5,1))

        cs = NodePath("dummy")
        cs.setState(self.camstate)
        # Do we really need to turn on the Shader Generator?
        #cs.setShaderAuto()
        if (auxbits):
            cs.setAttrib(AuxBitplaneAttrib.make(auxbits))
        self.camera.node().setInitialState(cs.getState())

        quadcamnode = Camera("filter-quad-cam")
        lens = OrthographicLens()
        lens.setFilmSize(2, 2)
        lens.setFilmOffset(0, 0)
        lens.setNearFar(-1000, 1000)
        quadcamnode.setLens(lens)
        quadcam = quad.attachNewNode(quadcamnode)
        
        self.region.setCamera(quadcam)

        dr = buffer.getDisplayRegion(0)
        self.setStackedClears(dr, self.rclears, self.wclears)
        if (auxtex):
            dr.setClearActive(GraphicsOutput.RTPAuxRgba0, 1)
            dr.setClearValue(GraphicsOutput.RTPAuxRgba0, Vec4(0.5,0.5,1.0,0.0))
        self.region.disableClears()
        if (self.isFullscreen()):
            self.win.disableClears()
        dr.setCamera(self.camera)
        dr.setActive(1)

        self.buffers.append(buffer)
        self.sizes.append((1, 1, 1))

        return quad