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) )
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()
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)
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
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
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
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
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
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")
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
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
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)
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
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
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()
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 = {}
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 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()
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
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)
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
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)
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
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()
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)
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
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
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
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)
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()
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
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
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)
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
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)
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
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
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
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)
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
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)
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
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)
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