class Scene(object): def __init__(self, sceneId=None): self.scene = NodePath('scene') if sceneId is not None: self.scene.setTag('scene-id', str(sceneId)) self.sceneId = sceneId agents = self.scene.attachNewNode('agents') self.agents = [ agents.attachNewNode('agent-0'), ] self.agents[0].setTag('agent-id', 'agent-0') self.worlds = dict() def getAllHouses(self): return self.scene.findAllMatches('**/house-*') def getAllRooms(self): return self.scene.findAllMatches('**/room-*') def getAllObjects(self): return self.scene.findAllMatches('**/object-*') def getAllAgents(self): return self.scene.findAllMatches('**/agents*') def getTotalNbHouses(self): nodepaths = self.getAllHouses() return len(nodepaths) if nodepaths else 0 def getTotalNbRooms(self): nodepaths = self.getAllRooms() return len(nodepaths) if nodepaths else 0 def getTotalNbObjects(self): nodepaths = self.getAllObjects() return len(nodepaths) if nodepaths else 0 def getTotalNbAgents(self): nodepaths = self.getAllAgents() return len(nodepaths) if nodepaths else 0 def hasGround(self): if self.scene.findAllMatches('**/ground*'): return True return False def __str__(self): return "Scene: %d houses, %d rooms, %d objects, %d agents" % ( self.getTotalNbHouses(), self.getTotalNbRooms(), self.getTotalNbObjects(), self.getTotalNbAgents()) __repr__ = __str__
class Scene(object): def __init__(self): self.scene = NodePath('scene') agents = self.scene.attachNewNode('agents') self.agents = [ agents.attachNewNode('agent-0'), ] self.worlds = dict() def getTotalNbHouses(self): nodepaths = self.scene.findAllMatches('**/house*') if nodepaths is not None: count = len(nodepaths) else: count = 0 return count def getTotalNbRooms(self): nodepaths = self.scene.findAllMatches('**/room*') if nodepaths is not None: count = len(nodepaths) else: count = 0 return count def getTotalNbObjects(self): nodepaths = self.scene.findAllMatches('**/object*') if nodepaths is not None: count = len(nodepaths) else: count = 0 return count def getTotalNbAgents(self): nodepaths = self.scene.findAllMatches('**/agents/*') if nodepaths is not None: count = len(nodepaths) else: count = 0 return count def __str__(self): return "Scene: %d houses, %d rooms, %d objects, %d agents" % ( self.getTotalNbHouses(), self.getTotalNbRooms(), self.getTotalNbObjects(), self.getTotalNbAgents()) __repr__ = __str__
class CogdoFlyingLevelQuadrant: notify = directNotify.newCategory('CogdoFlyingLevelQuadrant') def __init__(self, serialNum, model, level, parent): self.serialNum = serialNum self._model = model self._level = level self._root = NodePath('Quadrant' + `serialNum`) self._model.reparentTo(self._root) self._root.reparentTo(parent) self._visible = True self.platforms = {} self.gatherables = [] self.obstacles = [] self._playing = False self._obstaclesRoot = NodePath('obstacles') self._obstaclesRoot.reparentTo(self._root) self._initObstacles(self._obstaclesRoot) self._gatherablesRoot = NodePath('gatherables') self._gatherablesRoot.reparentTo(self._root) self._initGatherables(self._gatherablesRoot) self._platformsRoot = NodePath('platforms') self._platformsRoot.reparentTo(self._model) self._initPlatforms(self._platformsRoot) self._optimize() self.place() def _optimize(self): lightCones = NodePath('lightCones') for np in self._platformsRoot.findAllMatches('**/*lightCone*'): np.wrtReparentTo(lightCones) lightCones.reparentTo(self._model) node = self._model.find('**/ducts') if not node.isEmpty(): node.flattenStrong() for np in node.getChildren(): np.wrtReparentTo(self._model) node = self._model.find('**/nests') if not node.isEmpty(): for np in node.getChildren(): np.flattenStrong() np.wrtReparentTo(self._model) for np in self._model.findAllMatches('**/*LayerStack*'): np.wrtReparentTo(self._model) for np in self._model.find('**/static').getChildren(): np.wrtReparentTo(self._model) self._model.flattenMedium() def _initPlatforms(self, parent): platformModels = self._model.findAllMatches('**/%s' % Globals.Level.PlatformName) for platformModel in platformModels: platform = CogdoFlyingPlatform(platformModel, parent=parent) self.platforms[platform.getName()] = platform def _destroyPlatforms(self): for platform in self.platforms.values(): platform.destroy() del self.platforms def _initGatherables(self, parent): self.generateGatherables(self._model, parent=parent) if Globals.Level.SpawnLaffPowerupsInNests: self.generateNestPowerups(self._model, parent=parent) def generateNestPowerups(self, gatherableModel, parent): nests = gatherableModel.findAllMatches('**/%s;+s' % Globals.Level.LegalEagleNestName) for nest in nests: offset = Globals.Level.LaffPowerupNestOffset pickup = self._level.gatherableFactory.createPowerup(Globals.Level.GatherableTypes.LaffPowerup) pickup.reparentTo(parent) pickup.setPos(parent, nest.getPos(parent) + offset) if Globals.Level.AddSparkleToPowerups: sparkles = self._level.gatherableFactory.createSparkles(Vec4(1, 1, 1, 1), Vec4(1, 1, 0, 1), 10.0) sparkles.reparentTo(pickup) sparkles.setPos(0, 0, 1) sparkles.start() self.gatherables.append(pickup) def generateGatherables(self, gatherableModel, parent = None, spread = Globals.Level.GatherablesDefaultSpread): parent = parent or self._root mopath = Mopath.Mopath(name='gatherables') def generateMemos(): gatherPaths = gatherableModel.findAllMatches('**/%s' % Globals.Level.GatherablesPathName) for gatherPath in gatherPaths: mopath.loadNodePath(gatherPath) t = 0.0 while t < mopath.getMaxT(): pickup = self._level.gatherableFactory.createMemo() pickup.reparentTo(parent) mopath.goTo(pickup, t) self.gatherables.append(pickup) t += spread gatherPath.removeNode() angleSpread = 360.0 / Globals.Level.NumMemosInRing gatherPaths = gatherableModel.findAllMatches('**/%s' % Globals.Level.GatherablesRingName) for gatherPath in gatherPaths: mopath.loadNodePath(gatherPath) t = 0.0 while t < mopath.getMaxT(): angle = 0 r = 3 while angle < 360.0: pickup = self._level.gatherableFactory.createMemo() pickup.reparentTo(parent) mopath.goTo(pickup, t) pickup.setX(parent, pickup.getX() + r * math.cos(math.radians(angle))) pickup.setZ(parent, pickup.getZ() + r * math.sin(math.radians(angle))) self.gatherables.append(pickup) angle += angleSpread t += spread + 0.5 gatherPath.removeNode() def generatePropellers(): gatherables = gatherableModel.findAllMatches('**/%s' % Globals.Level.PropellerName) for gatherable in gatherables: pickup = self._level.gatherableFactory.createPropeller() pickup.reparentTo(gatherable.getParent()) pickup.setPos(parent, gatherable.getPos(parent)) self.gatherables.append(pickup) gatherable.removeNode() def generatePowerUps(): for powerupType, locName in Globals.Level.PowerupType2Loc.iteritems(): if powerupType == Globals.Level.GatherableTypes.LaffPowerup and Globals.Level.IgnoreLaffPowerups: continue gatherables = gatherableModel.findAllMatches('**/%s' % locName) for gatherable in gatherables: pickup = self._level.gatherableFactory.createPowerup(powerupType) pickup.reparentTo(parent) pickup.setPos(parent, gatherable.getPos(parent)) if Globals.Level.AddSparkleToPowerups: sparkles = self._level.gatherableFactory.createSparkles(Vec4(1, 1, 1, 1), Vec4(1, 1, 0, 1), 10.0) sparkles.reparentTo(pickup) sparkles.setPos(0, 0, 1) sparkles.start() self.gatherables.append(pickup) gatherable.removeNode() generateMemos() generatePropellers() generatePowerUps() def _initObstacles(self, parent): def initWhirlwinds(): obstacles = self._root.findAllMatches('**/%s' % Globals.Level.WhirlwindName) for obstacleLoc in obstacles: motionPath = self._model.find('**/%s%s' % (obstacleLoc.getName(), Globals.Level.WhirlwindPathName)) if motionPath.isEmpty(): motionPath = None obstacle = self._level.obstacleFactory.createWhirlwind(motionPath=motionPath) obstacle.model.reparentTo(parent) obstacle.model.setPos(parent, obstacleLoc.getPos(parent)) self.obstacles.append(obstacle) obstacleLoc.removeNode() return def initStreamers(): obstacles = self._model.findAllMatches('**/%s' % Globals.Level.StreamerName) for obstacleLoc in obstacles: obstacle = self._level.obstacleFactory.createFan() obstacle.model.reparentTo(parent) obstacle.model.setPos(parent, obstacleLoc.getPos(parent)) obstacle.model.setHpr(parent, obstacleLoc.getHpr(parent)) obstacle.model.setScale(parent, obstacleLoc.getScale(parent)) obstacle.setBlowDirection() if Globals.Level.AddParticlesToStreamers: particles = self._level.obstacleFactory.createStreamerParticles(Vec4(1, 1, 1, 1), Vec4(1, 1, 1, 1), 10.0) particles.reparentTo(obstacle.model) particles.start() self.obstacles.append(obstacle) obstacleLoc.removeNode() def initWalkingMinions(): motionPaths = self._model.findAllMatches('**/%s' % Globals.Level.MinionWalkingPathName) for motionPath in motionPaths: obstacle = self._level.obstacleFactory.createWalkingMinion(motionPath=motionPath) obstacle.model.reparentTo(parent) obstacle.model.setPos(parent, motionPath.getPos(parent)) self.obstacles.append(obstacle) def initFlyingMinions(): motionPaths = self._model.findAllMatches('**/%s' % Globals.Level.MinionFlyingPathName) for motionPath in motionPaths: obstacle = self._level.obstacleFactory.createFlyingMinion(motionPath=motionPath) obstacle.model.reparentTo(parent) obstacle.model.setPos(parent, motionPath.getPos(parent)) self.obstacles.append(obstacle) initWhirlwinds() initStreamers() initWalkingMinions() initFlyingMinions() def place(self): self._root.setPos(0, self._level.convertQuadNumToY(self.serialNum), 0) def destroy(self): if self._visible: self.offstage() self._destroyPlatforms() for obstacle in self.obstacles: obstacle.destroy() for gatherable in self.gatherables: gatherable.destroy() self._root.removeNode() del self._root del self._gatherablesRoot del self._obstaclesRoot del self._platformsRoot del self._level def onstage(self, elapsedTime = 0.0): if self._visible: return self._root.unstash() for obstacle in self.obstacles: obstacle.startMoving(elapsedTime) for gatherable in self.gatherables: gatherable.show() self._visible = True def offstage(self): if not self._visible: return self._root.stash() for obstacle in self.obstacles: obstacle.stopMoving() for gatherable in self.gatherables: gatherable.hide() self._visible = False def update(self, dt): if self._visible: for gatherable in self.gatherables: gatherable.update(dt) for obstacle in self.obstacles: obstacle.update(dt) def getModel(self): return self._root
class CogdoMazeFactory: def __init__(self, randomNumGen, width, height, frameWallThickness=Globals.FrameWallThickness, cogdoMazeData=CogdoMazeData): self._rng = RandomNumGen(randomNumGen) self.width = width self.height = height self.frameWallThickness = frameWallThickness self._cogdoMazeData = cogdoMazeData self.quadrantSize = self._cogdoMazeData.QuadrantSize self.cellWidth = self._cogdoMazeData.QuadrantCellWidth def getMazeData(self): if not hasattr(self, '_data'): self._generateMazeData() return self._data def createCogdoMaze(self, flattenModel=True): if not hasattr(self, '_maze'): self._loadAndBuildMazeModel(flatten=flattenModel) return CogdoMaze(self._model, self._data, self.cellWidth) def _gatherQuadrantData(self): self.openBarriers = [] barrierItems = range(Globals.TotalBarriers) self._rng.shuffle(barrierItems) for i in barrierItems[0:len(barrierItems) - Globals.NumBarriers]: self.openBarriers.append(i) self.quadrantData = [] quadrantKeys = self._cogdoMazeData.QuadrantCollisions.keys() self._rng.shuffle(quadrantKeys) i = 0 for y in xrange(self.height): for x in xrange(self.width): key = quadrantKeys[i] collTable = self._cogdoMazeData.QuadrantCollisions[key] angle = self._cogdoMazeData.QuadrantAngles[self._rng.randint(0, len(self._cogdoMazeData.QuadrantAngles) - 1)] self.quadrantData.append((key, collTable[angle], angle)) i += 1 if x * y >= self._cogdoMazeData.NumQuadrants: i = 0 def _generateBarrierData(self): data = [] for y in xrange(self.height): data.append([]) for x in xrange(self.width): if x == self.width - 1: ax = -1 else: ax = 1 if y == self.height - 1: ay = -1 else: ay = 1 data[y].append([ax, ay]) dirUp = 0 dirDown = 1 dirLeft = 2 dirRight = 3 def getAvailableDirections(ax, ay, ignore=None): dirs = [] if ax - 1 >= 0 and data[ay][(ax - 1)][BARRIER_DATA_RIGHT] == 1 and (ax, ay) != ignore: dirs.append(dirLeft) if ax + 1 < self.width and data[ay][ax][BARRIER_DATA_RIGHT] == 1 and (ax, ay) != ignore: dirs.append(dirRight) if ay - 1 >= 0 and data[(ay - 1)][ax][BARRIER_DATA_TOP] == 1 and (ax, ay) != ignore: dirs.append(dirDown) if ay + 1 < self.height and data[ay][ax][BARRIER_DATA_TOP] == 1 and (ax, ay) != ignore: dirs.append(dirUp) return dirs visited = [] def tryVisitNeighbor(ax, ay, ad): if ad == dirUp: if data[ay][ax] in visited: return None visited.append(data[ay][ax]) data[ay][ax][BARRIER_DATA_TOP] = 0 ay += 1 elif ad == dirDown: if data[(ay - 1)][ax] in visited: return None visited.append(data[(ay - 1)][ax]) data[(ay - 1)][ax][BARRIER_DATA_TOP] = 0 ay -= 1 elif ad == dirLeft: if data[ay][(ax - 1)] in visited: return None visited.append(data[ay][(ax - 1)]) data[ay][(ax - 1)][BARRIER_DATA_RIGHT] = 0 ax -= 1 elif ad == dirRight: if data[ay][ax] in visited: return None visited.append(data[ay][ax]) data[ay][ax][BARRIER_DATA_RIGHT] = 0 ax += 1 return (ax, ay) def openBarriers(x, y): dirs = getAvailableDirections(x, y) for dir in dirs: next = tryVisitNeighbor(x, y, dir) if next is not None: openBarriers(*next) return x = self._rng.randint(0, self.width - 1) y = self._rng.randint(0, self.height - 1) openBarriers(x, y) self._barrierData = data return def _generateMazeData(self): if not hasattr(self, 'quadrantData'): self._gatherQuadrantData() self._data = {} self._data['width'] = (self.width + 1) * self.frameWallThickness + self.width * self.quadrantSize self._data['height'] = (self.height + 1) * self.frameWallThickness + self.height * self.quadrantSize self._data['originX'] = int(self._data['width'] / 2) self._data['originY'] = int(self._data['height'] / 2) collisionTable = [] horizontalWall = [ 1 for x in xrange(self._data['width']) ] collisionTable.append(horizontalWall) for i in xrange(0, len(self.quadrantData), self.width): for y in xrange(self.quadrantSize): row = [ 1] for x in xrange(i, i + self.width): if x == 1 and y < self.quadrantSize / 2 - 2: newData = [] for j in self.quadrantData[x][1][y]: if j == 0: newData.append(2) else: newData.append(j + 0) row += newData + [1] else: row += self.quadrantData[x][1][y] + [1] collisionTable.append(row) collisionTable.append(horizontalWall[:]) barriers = Globals.MazeBarriers for i in xrange(len(barriers)): for coords in barriers[i]: collisionTable[coords[1]][coords[0]] = 0 y = self._data['originY'] for x in xrange(len(collisionTable[y])): if collisionTable[y][x] == 0: collisionTable[y][x] = 2 x = self._data['originX'] for y in xrange(len(collisionTable)): if collisionTable[y][x] == 0: collisionTable[y][x] = 2 self._data['collisionTable'] = collisionTable def _loadAndBuildMazeModel(self, flatten=False): self.getMazeData() self._model = NodePath('CogdoMazeModel') levelModel = CogdoUtil.loadMazeModel('level') self.quadrants = [] quadrantUnitSize = int(self.quadrantSize * self.cellWidth) frameActualSize = self.frameWallThickness * self.cellWidth size = quadrantUnitSize + frameActualSize halfWidth = int(self.width / 2) halfHeight = int(self.height / 2) i = 0 for y in xrange(self.height): for x in xrange(self.width): ax = (x - halfWidth) * size ay = (y - halfHeight) * size extension = '' if hasattr(getBase(), 'air'): extension = '.bam' filepath = self.quadrantData[i][0] + extension angle = self.quadrantData[i][2] m = self._createQuadrant(filepath, i, angle, quadrantUnitSize) m.setPos(ax, ay, 0) m.reparentTo(self._model) self.quadrants.append(m) i += 1 quadrantHalfUnitSize = quadrantUnitSize * 0.5 barrierModel = CogdoUtil.loadMazeModel('grouping_blockerDivider').find('**/divider') y = 3 for x in xrange(self.width): if x == (self.width - 1) / 2: continue ax = (x - halfWidth) * size ay = (y - halfHeight) * size - quadrantHalfUnitSize - (self.cellWidth - 0.5) b = NodePath('barrier') barrierModel.instanceTo(b) b.setPos(ax, ay, 0) b.reparentTo(self._model) offset = self.cellWidth - 0.5 for x in (0, 3): for y in xrange(self.height): ax = (x - halfWidth) * size - quadrantHalfUnitSize - frameActualSize + offset ay = (y - halfHeight) * size b = NodePath('barrier') barrierModel.instanceTo(b) b.setPos(ax, ay, 0) b.setH(90) b.reparentTo(self._model) offset -= 2.0 barrierModel.removeNode() levelModel.getChildren().reparentTo(self._model) for np in self._model.findAllMatches('**/*lightCone*'): CogdoUtil.initializeLightCone(np, 'fixed', 3) if flatten: self._model.flattenStrong() return self._model def _createQuadrant(self, filepath, serialNum, angle, size): root = NodePath('QuadrantRoot-%i' % serialNum) quadrant = loader.loadModel(filepath) quadrant.getChildren().reparentTo(root) root.setH(angle) return root
def traverse(self, nodePath, dnaStorage): root = NodePath('signroot') head_root = NodePath('root') wantDecalTest = base.config.GetBool('want-sign-decal-test', False) x = 0 for i in range(len(self.text)): tn = TextNode("text") tn.setText(self.text[i]) tn.setTextColor(self.color) font = dnaStorage.findFont(self.code) if font == None: raise DNAError.DNAError('Font code %s not found.' % self.code) tn.setFont(font) if i == 0 and 'b' in self.flags: tn.setTextScale(1.5) np = root.attachNewNode(tn) np.setScale(self.scale) np.setDepthWrite(0) if i % 2: np.setPos(x + self.stumble, 0, self.stomp) np.setR(-self.wiggle) else: np.setPos(x - self.stumble, 0, self.stomp) np.setR(self.wiggle) x += tn.getWidth() * np.getSx() + self.kern for i in range(root.getNumChildren()): c = root.getChild(i) c.setX(c.getX() - x / 2.) if self.width and self.height: for i in range(root.getNumChildren()): node = root.getChild(i) A = (node.getX() / (self.height / 2.)) B = (self.indent * math.pi / 180.) theta = A + B d = node.getY() x = math.sin(theta) * (self.height / 2.) y = (math.cos(theta) - 1) * (self.height / 2.) radius = math.hypot(x, y) if radius != 0: j = (radius + d) / radius x *= j y *= j node.setPos(x, 0, y) node.setR(node, (theta * 180.) / math.pi) collection = root.findAllMatches("**/+TextNode") for i in range(collection.getNumPaths()): xnp = collection.getPath(i) np2 = xnp.getParent().attachNewNode(xnp.node().generate()) np2.setTransform(xnp.getTransform()) xnp.removeNode() _np = nodePath.attachNewNode(root.node()) _np.setPosHpr(self.pos, self.hpr) if wantDecalTest: root.setEffect(DecalEffect.make()) else: _np.setDepthOffset(50) self.traverseChildren(_np, dnaStorage) _np.flattenStrong()
class GunGameLevelLoader: notify = directNotify.newCategory('GunGameLevelLoader') LevelData = {'momada': {'name': CIGlobals.ToonBattleOriginalLevel, 'camera': ( Point3(0.0, -25.8, 7.59), Vec3(0.0, 0.0, 0.0)), 'models': [ 'phase_11/models/lawbotHQ/LB_Zone03a.bam', 'phase_11/models/lawbotHQ/LB_Zone04a.bam', 'phase_11/models/lawbotHQ/LB_Zone7av2.bam', 'phase_11/models/lawbotHQ/LB_Zone08a.bam', 'phase_11/models/lawbotHQ/LB_Zone13a.bam', 'phase_10/models/cashbotHQ/ZONE17a.bam', 'phase_10/models/cashbotHQ/ZONE18a.bam', 'phase_11/models/lawbotHQ/LB_Zone22a.bam'], 'parents': [ render, 'EXIT', 'EXIT', 'EXIT', 'ENTRANCE', 'ENTRANCE', 'ENTRANCE', 'EXIT'], 'model_positions': [ Point3(0.0, 0.0, 0.0), Point3(-1.02, 59.73, 0.0), Point3(0.0, 74.77, 0.0), Point3(0.0, 89.37, -13.5), Point3(16.33, -136.53, 0.0), Point3(-1.01, -104.4, 0.0), Point3(0.65, -23.86, 0.0), Point3(-55.66, -29.01, 0.0)], 'model_orientations': [ Vec3(0.0, 0.0, 0.0), Vec3(0.0, 0.0, 0.0), Vec3(90.0, 0.0, 0.0), Vec3(180.0, 0.0, 0.0), Vec3(97.0, 0.0, 0.0), Vec3(359.95, 0.0, 0.0), Vec3(90.0, 0.0, 0.0), Vec3(270.0, 0.0, 0.0)], 'spawn_points': [ ( Point3(0, 0, 0), Vec3(0, 0, 0)), ( Point3(-20, 50, 0), Vec3(0, 0, 0)), ( Point3(20, 50, 0), Vec3(0, 0, 0)), ( Point3(0, 120, 0), Vec3(0, 0, 0)), ( Point3(0, 100, 0), Vec3(180, 0, 0)), ( Point3(-90, 0, 0), Vec3(0, 0, 0)), ( Point3(-170, 0, 0), Vec3(0, 0, 0)), ( Point3(-90, 50, 0), Vec3(0, 0, 0)), ( Point3(-170, 50, 0), Vec3(0, 0, 0)), ( Point3(35, 250, 0), Vec3(-90, 0, 0)), ( Point3(0, 285, 0), Vec3(180, 0, 0)), ( Point3(-185, 250, 0), Vec3(90, 0, 0))]}, 'dg': {'name': CIGlobals.DaisyGardens, 'camera': ( Point3(-33.13, -3.2, 48.62), Vec3(326.31, 332.68, 0.0)), 'dna': [ 'phase_8/dna/storage_DG.pdna', 'phase_8/dna/storage_DG_sz.pdna', 'phase_8/dna/daisys_garden_sz.pdna'], 'sky': 'TT', 'spawn_points': hoodMgr.dropPoints[CIGlobals.DaisyGardens]}, 'mml': {'name': CIGlobals.MinniesMelodyland, 'camera': ( Point3(-54.42, -91.05, 34.89), Vec3(315.29, 336.8, 0.0)), 'dna': [ 'phase_6/dna/storage_MM.pdna', 'phase_6/dna/storage_MM_sz.pdna', 'phase_6/dna/minnies_melody_land_sz.pdna'], 'sky': 'MM', 'spawn_points': hoodMgr.dropPoints[CIGlobals.MinniesMelodyland]}, 'oz': {'name': CIGlobals.OutdoorZone, 'camera': ( Point3(-54.42, -91.05, 34.89), Vec3(315.29, 336.8, 0.0)), 'dna': [ 'phase_6/dna/storage_OZ.pdna', 'phase_6/dna/storage_OZ_sz.pdna', 'phase_6/dna/outdoor_zone_sz.pdna'], 'sky': 'TT', 'spawn_points': hoodMgr.dropPoints[CIGlobals.OutdoorZone]}, 'cbhq': {'name': CIGlobals.CashbotHQ, 'camera': ( Point3(302.64, 5.0, 15.2), Vec3(135.0, 341.57, 0.0)), 'model': 'phase_10/models/cogHQ/CashBotShippingStation.bam', 'sky': None, 'spawn_points': hoodMgr.dropPoints[CIGlobals.CashbotHQ]}, 'sbf': {'name': CIGlobals.SellbotFactory, 'camera': ( Point3(0, 0, 0), Vec3(0, 0, 0)), 'model': 'phase_9/models/cogHQ/SelbotLegFactory.bam', 'sky': 'cog', 'sky_scale': 10.0, 'occluders': 'phase_9/models/cogHQ/factory_sneak_occluders.egg', 'spawn_points': {GGG.Teams.BLUE: [ ( Point3(13, 30, 3.73), Point3(0, 0, 0)), (Point3(21, 30, 3.73), Point3(0, 0, 0)), (Point3(29, 30, 3.73), Point3(0, 0, 0)), ( Point3(13, 20, 3.73), Point3(0, 0, 0)), (Point3(21, 20, 3.73), Point3(0, 0, 0)), (Point3(29, 30, 3.73), Point3(0, 0, 0))], GGG.Teams.RED: [ ( Point3(-644.43, 378.12, 8.73), Point3(270, 0, 0)), (Point3(-644.43, 370.75, 8.73), Point3(270, 0, 0)), (Point3(-644.43, 363.22, 8.73), Point3(270, 0, 0)), ( Point3(-659.05, 378.12, 8.73), Point3(270, 0, 0)), (Point3(-659.05, 370.75, 8.73), Point3(270, 0, 0)), (Point3(-659.05, 363.22, 8.73), Point3(270, 0, 0))]}, 'flag_points': {GGG.Teams.BLUE: [Point3(213.23, 340.59, 19.73), Point3(90, 0, 0)], GGG.Teams.RED: [ Point3(-543.6, 595.79, 9.73), Point3(270, 0, 0)]}, 'flagpoint_points': {GGG.Teams.BLUE: [Point3(-543.6, 595.79, 9.73), Point3(270, 0, 0)], GGG.Teams.RED: [ Point3(213.23, 340.59, 19.73), Point3(0, 0, 0)]}}, 'ttc': {'name': CIGlobals.ToontownCentral, 'dna': [ 'phase_4/dna/storage_TT.pdna', 'phase_4/dna/storage_TT_sz.pdna', 'phase_4/dna/new_ttc_sz.pdna'], 'sky': 'TT', 'spawn_points': [ (9.90324401855, 91.9139556885, 8.0364112854, -545.909545898, 0.0, 0.0), (77.9181442261, 50.953086853, 7.52815723419, -598.509460449, 0.0, 0.0), (93.7379760742, 6.37303066254, 7.99749088287, -626.209533691, 0.0, 0.0), (39.0383415222, -81.5989837646, 8.01874637604, -694.309265137, 0.0, 0.0), (-19.2093048096, -95.1359481812, 8.07303524017, -731.409240723, 0.0, 0.0), (-84.4093933105, -45.4780502319, 8.06541728973, -781.809143066, 0.0, 0.0), (-92.2512283325, 2.41426730156, 8.03108692169, -811.70916748, 0.0, 0.0), (46.8868179321, 81.3593673706, 8.04793071747, -955.309509277, 0.0, 0.0), (32.3203735352, 90.0017929077, 8.06353855133, -884.409301758, 0.0, 0.0)], 'cap_point': Point3(-1.5, 0, 0)}} SkyData = {'TT': 'phase_3.5/models/props', 'MM': 'phase_6/models/props', 'cog': 'phase_9/models/cogHQ', 'MovingSkies': [ 'TT']} def __init__(self, mg): self.mg = mg self.levelName = None self.dnaStore = DNAStorage() self.loadingText = None self.levelGeom = None self.skyUtil = None self.skyModel = None self.occluders = None self.momadaAreas = [] self.momadaAreaName2areaModel = {} return def getFlagPoint_Point(self, team): return self.LevelData[self.levelName]['flagpoint_points'][team] def getFlagPoint(self, team): return self.LevelData[self.levelName]['flag_points'][team] def getCapturePoint(self): return self.LevelData[self.levelName]['cap_point'] def setLevel(self, level): self.levelName = level def getLevel(self): return self.levelName def getCameraOfCurrentLevel(self): return self.LevelData[self.getLevel()]['camera'] def getSpawnPoints(self): pointData = self.LevelData[self.levelName]['spawn_points'] if self.levelName == 'momada': return pointData if self.mg.gameMode in [GGG.GameModes.CASUAL, GGG.GameModes.KOTH]: array = [] for posAndHpr in pointData: array.append(( Point3(posAndHpr[0], posAndHpr[1], posAndHpr[2]), Vec3(posAndHpr[3], posAndHpr[4], posAndHpr[5]))) else: if self.mg.gameMode == GGG.GameModes.CTF: array = pointData[self.mg.team] return array def getNameOfCurrentLevel(self): return self.LevelData[self.getLevel()]['name'] def load(self): self.unload() if self.loadingText: self.loadingText.destroy() self.loadingText = None self.loadingText = OnscreenText(text='', font=CIGlobals.getMinnieFont(), fg=(1, 1, 1, 1)) self.loadingText.setBin('gui-popup', 0) base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() if self.levelName == 'momada': self.__momadaLoad() else: if self.levelName in ('cbhq', 'sbf'): modelPath = self.LevelData[self.levelName]['model'] self.levelGeom = loader.loadModel(modelPath) self.levelGeom.flattenMedium() self.levelGeom.reparentTo(render) if self.LevelData[self.levelName]['sky'] != None: self.skyModel = loader.loadModel(self.SkyData['cog'] + '/cog_sky.bam') self.skyUtil = SkyUtil() self.skyUtil.startSky(self.skyModel) self.skyModel.reparentTo(render) self.skyModel.setScale(self.LevelData[self.levelName].get('sky_scale', 1.0)) if self.LevelData[self.levelName].get('occluders'): self.occluders = loader.loadModel(self.LevelData[self.levelName]['occluders']) for occluderNode in self.occluders.findAllMatches('**/+OccluderNode'): base.render.setOccluder(occluderNode) occluderNode.node().setDoubleSided(True) if self.levelName == 'sbf': base.camLens.setFar(250) else: dnaFiles = self.LevelData[self.levelName]['dna'] skyType = self.LevelData[self.levelName]['sky'] skyPhase = self.SkyData[skyType] loadDNAFile(self.dnaStore, 'phase_4/dna/storage.pdna') for index in range(len(dnaFiles)): if index == len(dnaFiles) - 1: node = loadDNAFile(self.dnaStore, dnaFiles[index]) if node.getNumParents() == 1: self.levelGeom = NodePath(node.getParent(0)) self.levelGeom.reparentTo(hidden) else: self.levelGeom = hidden.attachNewNode(node) if self.levelName == 'ttc' and dnaFiles[index] == 'phase_4/dna/new_ttc_sz.pdna': self.levelGeom.find('**/prop_gazebo_DNARoot').removeNode() else: self.levelGeom.flattenMedium() gsg = base.win.getGsg() if gsg: self.levelGeom.prepareScene(gsg) self.levelGeom.reparentTo(render) else: loadDNAFile(self.dnaStore, dnaFiles[index]) children = self.levelGeom.findAllMatches('**/*doorFrameHole*') for child in children: child.hide() self.skyModel = loader.loadModel(skyPhase + '/' + skyType + '_sky.bam') self.skyUtil = SkyUtil() self.skyUtil.startSky(self.skyModel) self.skyModel.reparentTo(camera) ce = CompassEffect.make(NodePath(), CompassEffect.PRot | CompassEffect.PZ) self.skyModel.node().setEffect(ce) if self.loadingText: self.loadingText.destroy() self.loadingText = None return def __momadaLoad(self): def attachArea(itemNum): name = 'MomadaArea-%s' % itemNum area = self.momadaAreaName2areaModel.get(name) parents = self.LevelData['momada']['parents'] parent = parents[itemNum] if type(parent) == type(''): parent = self.momadaAreas[itemNum - 1].find('**/' + parent) pos = self.LevelData['momada']['model_positions'][itemNum] hpr = self.LevelData['momada']['model_orientations'][itemNum] area.reparentTo(parent) area.setPos(pos) area.setHpr(hpr) _numItems = 0 name = None for item in self.LevelData['momada']['models']: name = 'MomadaArea-%s' % _numItems area = loader.loadModel(item) self.momadaAreas.append(area) self.momadaAreaName2areaModel[name] = area attachArea(_numItems) _numItems += 1 self.notify.info('Loaded and attached %s momada areas.' % _numItems) return def unload(self): render.clearOccluder() if self.levelName == 'sbf': base.camLens.setFar(CIGlobals.DefaultCameraFar) if self.levelName == 'momada': for area in self.momadaAreas: self.momadaAreas.remove(area) area.removeNode() del area self.momadaAreas = [] self.momadaAreaName2areaModel = {} else: if self.occluders: self.occluders.removeNode() self.occluders = None if self.skyUtil: self.skyUtil.stopSky() self.skyUtil = None if self.skyModel: self.skyModel.removeNode() self.skyModel = None if self.levelGeom: self.levelGeom.removeNode() self.levelGeom = None return def cleanup(self): self.momadaAreas = None self.momadaAreaName2areaModel = None if self.dnaStore: self.dnaStore.reset_nodes() self.dnaStore.reset_hood_nodes() self.dnaStore.reset_place_nodes() self.dnaStore.reset_hood() self.dnaStore.reset_fonts() self.dnaStore.reset_DNA_vis_groups() self.dnaStore.reset_textures() self.dnaStore.reset_block_numbers() self.dnaStore.reset_block_zones() self.dnaStore.reset_suit_points() self.dnaStore = None return
class cMinicolumn: def __init__(self, nameOfLayer, nOfCellsPerColumn): self.cells = [] for i in range(nOfCellsPerColumn): n = cCell(self) self.cells.append(n) self.parentLayer = nameOfLayer self.transparency = 1.0 self.gfxCreated = False self.LodDistance1Stored = 100.0 self.LodDistance2Stored = 5000.0 self.bursting = False self.active = False self.oneOfCellPredictive = False self.oneOfCellCorrectlyPredicted = False self.oneOfCellFalselyPredicted = False def CreateGfx(self, loader, idx): # __node # / \ # cellsNodePath columnBox self.lod = LODNode("columnLOD") # Level of detail node for Column self.__node = NodePath( self.lod ) # NodePath(PandaNode('column'))# loader.loadModel("models/box") self.__node.setPos(0, 0, 0) self.__node.setScale(1, 1, 1) # self.__node.setTag('clickable',str(idx))#to be able to click on it self.__columnBox = loader.loadModel("models/cube") self.__columnBox.setPos( 0, 0, -0.5 + (0 if len(self.cells) == 0 else len(self.cells) * (1 + CELL_OFFSET) / 2)) self.__columnBox.setScale( 0.5, 0.5, 0.5 * (1 if len(self.cells) == 0 else len(self.cells) * (1 + CELL_OFFSET))) self.__columnBox.setName("columnBox") self.__cellsNodePath = NodePath( PandaNode("cellsNode")) # to pack all cells into one node path self.__cellsNodePath.setName("column") self.__cellsNodePath.setTag( "id", str(idx)) # to be able to retrieve index of column for mouse click self.lod.addSwitch(100.0, 0.0) self.lod.addSwitch(5000.0, 100.0) self.__cellsNodePath.reparentTo(self.__node) self.__columnBox.reparentTo(self.__node) z = 0 idx = 0 for n in self.cells: n.CreateGfx(loader, idx) idx += 1 n.getNode().setPos(0, 0, z) z += 1 + CELL_OFFSET n.getNode().reparentTo(self.__cellsNodePath) self.gfxCreated = True def LODUpdateSwitch(self, lodDistance, lodDistance2): self.lodDistance1Stored = lodDistance self.lodDistance2Stored = lodDistance2 self.lod.clearSwitches() self.lod.addSwitch(lodDistance, 0.0) self.lod.addSwitch(lodDistance2, lodDistance) def LODUpdateSwitch_long(self): self.lod.clearSwitches() self.lod.addSwitch(self.lodDistance2Stored, 0.0) self.lod.addSwitch(self.lodDistance2Stored, self.lodDistance2Stored) def LODUpdateSwitch_normal(self): self.LODUpdateSwitch(self.lodDistance1Stored, self.lodDistance2Stored) def UpdateState(self, bursting, activeColumn, oneOfCellPredictive, oneOfCellCorrectlyPredicted, oneOfCellFalselyPredicted): self.bursting = bursting self.active = activeColumn self.oneOfCellPredictive = oneOfCellPredictive self.oneOfCellCorrectlyPredicted = oneOfCellCorrectlyPredicted self.oneOfCellFalselyPredicted = oneOfCellFalselyPredicted # update column box color (for LOD in distance look) if self.oneOfCellCorrectlyPredicted: COL_COLUMN_ONEOFCELLCORRECTLY_PREDICTED.setW(self.transparency) col = COL_COLUMN_ONEOFCELLCORRECTLY_PREDICTED self.__columnBox.setColor(col) elif self.oneOfCellFalselyPredicted: COL_COLUMN_ONEOFCELLFALSELY_PREDICTED.setW(self.transparency) col = COL_COLUMN_ONEOFCELLFALSELY_PREDICTED self.__columnBox.setColor(col) elif self.oneOfCellPredictive: COL_COLUMN_ONEOFCELLPREDICTIVE.setW(self.transparency) col = COL_COLUMN_ONEOFCELLPREDICTIVE self.__columnBox.setColor(col) elif self.active: COL_COLUMN_ACTIVE.setW(self.transparency) col = COL_COLUMN_ACTIVE self.__columnBox.setColor(col) else: COL_COLUMN_INACTIVE.setW(self.transparency) col = COL_COLUMN_INACTIVE self.__columnBox.setColor(col) # for n in self.cells: # n.active = active # n.UpdateState() def getNode(self): return self.__node def updateWireframe(self, value): for cell in self.cells: cell.updateWireframe(value) if value: self.__columnBox.setRenderModeFilledWireframe(LColor(0, 0, 0, 1.0)) else: self.__columnBox.setRenderModeFilled() # -- Create proximal synapses # inputObjects - list of names of inputs(areas) # inputs - panda vis input object # synapses - list of the second points of synapses (first point is this cortical column) # NOTE: synapses are now DENSE def CreateProximalSynapses(self, inputObjects, inputs, synapses): for child in self.__cellsNodePath.getChildren(): if child.getName() == "ProximalSynapseLine": child.removeNode() printLog("Creating proximal synapses", verbosityMedium) printLog("To inputs called:" + str(inputObjects), verbosityMedium) printLog("Synapses count:" + str(len(synapses)), verbosityMedium) printLog("active:" + str(sum([i for i in synapses])), verbosityHigh) # inputs are divided into separate items in list - [input1,input2,input3] # synapses are one united array [1,0,0,1,0,1,0...] # length is the same # synapses can be connected to one input or to several inputs # if to more than one - split synapses array synapsesDiv = [] offset = 0 for inputObj in inputObjects: synapsesDiv.append(synapses[offset:offset + inputs[inputObj].count]) offset += inputs[inputObj].count for i in range(len(synapsesDiv)): # for each input object inputs[ inputObjects[i]].resetProximalFocus() # clear color highlight for y in range(len(synapsesDiv[i]) ): # go through every synapse and check activity if synapsesDiv[i][y] == 1: form = GeomVertexFormat.getV3() vdata = GeomVertexData("ProximalSynapseLine", form, Geom.UHStatic) vdata.setNumRows(1) vertex = GeomVertexWriter(vdata, "vertex") vertex.addData3f( inputs[inputObjects[i]].inputBits[y].getNode().getPos( self.__node)) vertex.addData3f(0, 0, 0) # vertex.addData3f(self.__node.getPos()) # printLog("Inputs:"+str(i)+"bits:"+str(y)) # printLog(inputs[i].inputBits[y].getNode().getPos(self.__node)) # highlight inputs[inputObjects[i]].inputBits[y].setProximalFocus( ) # highlight connected bits prim = GeomLines(Geom.UHStatic) prim.addVertices(0, 1) geom = Geom(vdata) geom.addPrimitive(prim) node = GeomNode("ProximalSynapse") node.addGeom(geom) nodePath = self.__cellsNodePath.attachNewNode(node) nodePath.setRenderModeThickness(2) # color of the line if inputs[inputObjects[i]].inputBits[y].active: nodePath.setColor(COL_PROXIMAL_SYNAPSES_ACTIVE) else: nodePath.setColor(COL_PROXIMAL_SYNAPSES_INACTIVE) def setTransparency(self, transparency): self.transparency = transparency for cell in self.cells: cell.setTransparency(transparency) self.UpdateState(self.bursting, self.active, self.oneOfCellPredictive, self.oneOfCellCorrectlyPredicted, self.oneOfCellFalselyPredicted) def DestroyProximalSynapses(self): for syn in self.__cellsNodePath.findAllMatches("ProximalSynapse"): syn.removeNode() def DestroyDistalSynapses(self): for cell in self.cells: cell.DestroyDistalSynapses() cell.resetPresynapticFocus() # also reset distal focus def getDescription(self): txt = "" txt += "Active:" + str(self.active) + "\n" txt += "One of cell is predictive:" + str( self.oneOfCellPredictive) + "\n" txt += "One of cell correctly predicted:" + str( self.oneOfCellCorrectlyPredicted) + "\n" txt += "One of cell false predicted:" + str( self.oneOfCellFalselyPredicted) + "\n" return txt
class CharSelection(DirectObject): notify = directNotify.newCategory('CharSelection') NO_TOON = "Empty Slot" PLAY = "Play" CREATE = "Create" TITLE = "Pick A Toon To Play" def __init__(self, avChooser): self.avChooser = avChooser self.choice = None self.charList = None self.charNameLabel = None self.charButtons = [] self.playOrCreateButton = None self.deleteButton = None self.quitButton = None self.title = None self.stageToon = None self.stageToonRoot = None self.deleteConf = None self.frame = None self.stageFSM = ClassicFSM.ClassicFSM('StageFSM', [ State.State('off', self.enterOff, self.exitOff), State.State('loadSZ', self.enterLoadSZ, self.exitLoadSZ), State.State('onStage', self.enterOnStage, self.exitOnStage) ], 'off', 'off') self.stageFSM.enterInitialState() self.selectionFSM = ClassicFSM.ClassicFSM('CharSelection', [ State.State('off', self.enterOff, self.exitOff), State.State('character', self.enterCharSelected, self.exitCharSelected), State.State('empty', self.enterEmptySelected, self.exitEmptySelected) ], 'off', 'off') self.selectionFSM.enterInitialState() self.szGeom = None self.olc = None self.asyncSZLoadStatus = False self.isNewToon = False self.newToonSlot = None self.camIval = None self.stAnimSeq = None self.newToonAnnounceSfx = base.loadSfx( "phase_4/audio/sfx/King_Crab.ogg") self.newToonDrumrollSfx = base.loadSfx( "phase_5/audio/sfx/SZ_MM_drumroll.ogg") self.newToonRevealSfx = base.loadSfx( "phase_5/audio/sfx/SZ_MM_fanfare.ogg") self.dnaStore = DNAStorage() loader.loadDNAFile(self.dnaStore, 'phase_4/dna/pickatoon/storage_pickatoon.pdna') def __setupStageToon(self): self.stageToonRoot = render.attachNewNode('stageToonRoot') self.stageToon = Toon(base.cr) self.stageToon.setPosHpr(0, 0, 0, 0, 0, 0) self.stageToon.reparentTo(self.stageToonRoot) def cleanupStageToon(self): if self.stageToon != None: self.stageToon.disable() self.stageToon.delete() self.stageToon = None if self.stageToonRoot != None: self.stageToonRoot.removeNode() self.stageToonRoot = None def enterOff(self): pass def exitOff(self): pass def __async_loadSZTask(self, task=None): dnas = HOOD_ID_2_DNA[self.choice.lastHood] for i in xrange(len(dnas)): dnaFile = dnas[i] if i == len(dnas) - 1: node = loader.loadDNAFile(self.dnaStore, dnaFile) if node.getNumParents() == 1: self.szGeom = NodePath(node.getParent(0)) self.szGeom.reparentTo(render) else: self.szGeom = render.attachNewNode(node) # The 2D trees should not be flattened, to do that, we're going to traverse # the scene graph for all trees, use #wrtReparentTo(render) on them, flatten # the scene with #flattenStrong(), and finally #wrtReparentTo(self.szGeom) # the trees back to the main scene node so they get cleaned up properly. trees = self.szGeom.findAllMatches('**/*tree*') #self.szGeom.find("**/shadow").removeNode() #from panda3d.core import CullBinAttrib #self.szGeom.find("**/shadow_crack").setAttrib(CullBinAttrib.make("foreground", 10), 10) #shs = self.szGeom.findAllMatches("**/*shadow*") #for sh in shs: # sh.removeNode() # self.szGeom.ls() for tree in trees: tree.wrtReparentTo(render) self.szGeom.flattenStrong() for tree in trees: tree.wrtReparentTo(self.szGeom) else: loader.loadDNAFile(self.dnaStore, dnaFile) self.olc = ZoneUtil.getOutdoorLightingConfig(self.choice.lastHood) self.olc.setup() self.olc.apply() CIGlobals.preRenderScene(render) self.asyncSZLoadStatus = True #base.accept('l', render.ls) if task: return task.done def enterLoadSZ(self): self.loadingDlg = Dialog.GlobalDialog("Loading...") self.loadingDlg.show() base.cr.renderFrame() base.cr.renderFrame() self.notify.info("Polling for SZ to load") self.asyncSZLoadStatus = False self.__async_loadSZTask() base.doNextFrame(self.stageFSM.request, ['onStage']) def exitLoadSZ(self): if hasattr(self, 'loadingDlg'): self.loadingDlg.cleanup() del self.loadingDlg def __changeCamFOV(self, val): base.camLens.setMinFov(val / (4. / 3.)) def enterOnStage(self): dna = self.choice.dna name = self.choice.name self.stageToon.setName(name) self.stageToon.setDNAStrand(dna) self.stageToon.nametag.setNametagColor( NametagGlobals.NametagColors[NametagGlobals.CCLocal]) self.stageToon.nametag.setActive(0) self.stageToon.nametag.nametag3d.request('Rollover') self.stageToon.nametag.unmanage(base.marginManager) self.stageToon.nametag.updateAll() self.stageToon.animFSM.request('neutral') self.stageToon.setPosHpr(0, 0, 0, 10, 0, 0) self.stageToon.show() dat = HOOD_STAGE_DATA[self.choice.lastHood] self.stageToonRoot.setPos(dat[2]) self.stageToonRoot.setHpr(dat[3]) camera.reparentTo(self.stageToonRoot) camera.setPos(dat[0]) camera.lookAt(self.stageToonRoot, 0, 0, 3) startHpr = camera.getHpr() camera.setPos(dat[1]) camera.lookAt(self.stageToonRoot, 0, 0, 3) endHpr = camera.getHpr() self.camIval = Parallel( LerpPosInterval(camera, 5.0, dat[1] - (1.6, 0, 0), dat[0] - (1.6, 0, 0), blendType='easeInOut'), LerpQuatInterval(camera, 5.0, hpr=endHpr, startHpr=startHpr, blendType='easeInOut'), LerpFunc(self.__changeCamFOV, duration=5.0, fromData=80.0, toData=CIGlobals.DefaultCameraFov, blendType='easeInOut')) if self.isNewToon: self.camIval.append( Sequence( Func(self.stageToon.hide), Func(base.stopMusic), SoundInterval(self.newToonAnnounceSfx, startTime=1.674, duration=4.047), SoundInterval(self.newToonDrumrollSfx), Func(self.stageToon.pose, 'tele', self.stageToon.getNumFrames('tele')), Func(self.newToonAppear), Func(self.stageToon.show), SoundInterval(self.newToonRevealSfx), Func(base.cr.playTheme))) else: self.camIval.append( Sequence(Func(self.showActionButtons), Func(self.enableAllCharButtons), Wait(5.0), Func(self.beginRandomAnims))) self.camIval.start() def hideActionButtons(self): self.playOrCreateButton.hide() self.deleteButton.hide() def showActionButtons(self): self.playOrCreateButton.show() self.deleteButton.show() def newToonAppear(self): self.stopSTAnimSeq() self.stAnimSeq = Sequence( Func(self.stageToon.animFSM.request, 'teleportIn'), Wait(2.0), ActorInterval(self.stageToon, 'wave'), Func(self.stageToon.loop, 'neutral'), Func(self.beginRandomAnims), Func(self.enableAllCharButtons), Func(self.showActionButtons)) self.stAnimSeq.start() def stopSTAnimSeq(self): if self.stAnimSeq: self.stAnimSeq.finish() self.stAnimSeq = None def unloadSZGeom(self): if self.szGeom: self.szGeom.removeNode() self.szGeom = None if self.olc: self.olc.cleanup() self.olc = None def beginRandomAnims(self): self.stageToon.startLookAround() taskMgr.doMethodLater(random.uniform(*ST_ANIM_IVAL), self.__doRandomSTAnim, "doRandomSTAnim") def __doRandomSTAnim(self, task): anim = random.choice(ST_RANDOM_ANIMS) self.stopSTAnimSeq() self.stageToon.stopLookAround() head = self.stageToon.getPart('head') if anim == 'read': self.stAnimSeq = Sequence( Func(self.stageToon.lerpLookAt, head, (0, -15, 0)), Func(self.stageToon.animFSM.request, 'openBook'), Wait(0.5), Func(self.stageToon.animFSM.request, 'readBook'), Wait(2.0), Func(self.stageToon.lerpLookAt, head, (0, 0, 0)), Func(self.stageToon.animFSM.request, 'closeBook'), Wait(1.75), Func(self.stageToon.loop, 'neutral'), Func(self.stageToon.startLookAround)) else: self.stageToon.lerpLookAt(head, (0, 0, 0)) self.stAnimSeq = Sequence(ActorInterval(self.stageToon, anim), Func(self.stageToon.loop, 'neutral'), Func(self.stageToon.startLookAround)) self.stAnimSeq.start() task.delayTime = random.uniform(*ST_ANIM_IVAL) return task.again def endRandomAnims(self): taskMgr.remove("doRandomSTAnim") self.stopSTAnimSeq() def exitOnStage(self): self.isNewToon = False if self.camIval: self.camIval.finish() self.camIval = None self.endRandomAnims() self.stopSTAnimSeq() camera.reparentTo(render) camera.setPosHpr(0, 0, 0, 0, 0, 0) #base.transitions.fadeScreen(1.0) self.unloadSZGeom() self.stageToon.hide() def enterCharSelected(self): self.playOrCreateButton['text'] = self.PLAY self.playOrCreateButton['extraArgs'] = ['play'] #aspect2d.hide() def exitCharSelected(self): self.playOrCreateButton.hide() self.deleteButton.hide() def enterEmptySelected(self): self.charNameLabel.setText(self.NO_TOON) self.playOrCreateButton['text'] = self.CREATE self.playOrCreateButton['extraArgs'] = ['create'] self.playOrCreateButton.show() def exitEmptySelected(self): self.playOrCreateButton.hide() def __action(self, action): for btn in self.charButtons: if btn['state'] == DGG.DISABLED: self.slot = btn.getPythonTag('slot') break func = None arg = None doFade = True if action == 'delete': func = self.deleteToon arg = self.choice.avId doFade = False elif action == 'play': func = self.playGame arg = self.choice.slot elif action == 'create': func = self.enterMAT elif action == 'quit': func = sys.exit doFade = False if doFade: base.transitions.fadeOut(0.3) if arg != None: Sequence(Wait(0.31), Func(func, arg)).start() else: Sequence(Wait(0.31), Func(func)).start() else: if arg != None: func(arg) else: func() def playGame(self, slot): messenger.send("avChooseDone", [self.avChooser.getAvChoiceBySlot(slot)]) def enterMAT(self): messenger.send("enterMakeAToon", [self.slot]) def deleteToon(self, avId): # Show a confirmation message self.deleteConf = Dialog.GlobalDialog( message='This will delete {0} forever.\n\nAre you sure?'.format( self.avChooser.getNameFromAvId(avId)), style=Dialog.YesNo, doneEvent='deleteConfResponse', extraArgs=[avId]) self.acceptOnce('deleteConfResponse', self.__handleDeleteConfResponse) self.deleteConf.show() def __handleDeleteConfResponse(self, avId): doneStatus = self.deleteConf.getValue() if doneStatus: # Alright, they pressed yes. No complaining to us. self.avChooser.avChooseFSM.request("waitForToonDelResponse", [avId]) else: self.deleteConf.cleanup() self.deleteConf = None def __handleCharButton(self, slot): for btn in self.charButtons: if btn.getPythonTag('slot') == slot: btn['state'] = DGG.DISABLED else: btn['state'] = DGG.NORMAL if self.avChooser.hasToonInSlot(slot): self.choice = self.avChooser.getAvChoiceBySlot(slot) self.selectionFSM.request('character') self.stageFSM.request('loadSZ') else: self.selectionFSM.request('empty') self.stageFSM.request('off') def disableAllCharButtons(self): for btn in self.charButtons: btn['state'] = DGG.DISABLED def enableAllCharButtons(self): for btn in self.charButtons: if not self.choice or btn.getPythonTag('slot') != self.choice.slot: btn['state'] = DGG.NORMAL def load(self, newToonSlot=None): self.isNewToon = newToonSlot is not None self.newToonSlot = newToonSlot base.transitions.noTransitions() base.cr.renderFrame() base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4. / 3.)) self.__setupStageToon() self.title = DirectLabel(text=self.TITLE, text_font=CIGlobals.getMickeyFont(), text_fg=(1, 0.9, 0.1, 1), relief=None, text_scale=0.13, pos=(0, 0, 0.82)) self.charNameLabel = OnscreenText(text="", font=CIGlobals.getMickeyFont(), pos=(-0.25, 0.5, 0), fg=(1, 0.9, 0.1, 1.0)) self.charNameLabel.hide() self.frame = DirectFrame() self.frame['image'] = DGG.getDefaultDialogGeom() self.frame['image_color'] = CIGlobals.DialogColor self.frame['image_scale'] = (-0.9, -0.9, 0.8) self.frame['image_pos'] = (0.82, 0, -0.125) self.playOrCreateButton = DirectButton( text="", pos=(0.8125, 0, -0.35), command=self.__action, geom=CIGlobals.getDefaultBtnGeom(), text_scale=0.06, relief=None, text_pos=(0, -0.01)) self.playOrCreateButton.hide() self.deleteButton = DirectButton(text="Delete", pos=(0.8125, 0, -0.45), command=self.__action, extraArgs=['delete'], geom=CIGlobals.getDefaultBtnGeom(), text_scale=0.06, relief=None, text_pos=(0, -0.01)) self.deleteButton.hide() self.quitButton = DirectButton(text="Quit", pos=(-1.10, 0, -0.925), command=self.__action, extraArgs=['quit'], text_scale=0.06, geom=CIGlobals.getDefaultBtnGeom(), relief=None, text_pos=(0, -0.01)) for slot in range(6): if self.avChooser.hasToonInSlot(slot): choice = self.avChooser.getAvChoiceBySlot(slot) text = choice.name else: text = self.NO_TOON btn = CIGlobals.makeDefaultScrolledListBtn( text=text, text_scale=0.06, command=self.__handleCharButton, extraArgs=[slot]) btn.setPythonTag('slot', slot) self.charButtons.append(btn) btn['state'] = DGG.NORMAL self.charList = CIGlobals.makeDefaultScrolledList( pos=(0.75, 0, -0.225), listZorigin=-0.43, listFrameSizeZ=0.51, arrowButtonScale=0.0, items=self.charButtons, parent=self.frame) if self.isNewToon: self.__handleCharButton(self.newToonSlot) self.disableAllCharButtons() def unload(self): self.selectionFSM.requestFinalState() self.stageFSM.requestFinalState() self.cleanupStageToon() self.choice = None if self.frame: self.frame.destroy() self.frame = None if self.charButtons: for btn in self.charButtons: btn.destroy() self.charButtons = None if self.deleteConf: self.deleteConf.cleanup() self.deleteConf = None if self.charList: self.charList.destroy() self.charList = None if self.charNameLabel: self.charNameLabel.destroy() self.charNameLabel = None if self.playOrCreateButton: self.playOrCreateButton.destroy() self.playOrCreateButton = None if self.deleteButton: self.deleteButton.destroy() self.deleteButton = None if self.quitButton: self.quitButton.destroy() self.quitButton = None if self.title: self.title.destroy() self.title = None base.camera.setPos(0, 0, 0) base.camera.setHpr(0, 0, 0) base.transitions.noTransitions() del self.selectionFSM
class TownLoader(StateData): notify = directNotify.newCategory("TownLoader") def __init__(self, hood, parentFSMState, doneEvent): self.hood = hood self.parentFSMState = parentFSMState StateData.__init__(self, doneEvent) self.fsm = ClassicFSM('TownLoader', [ State('start', self.enterStart, self.exitStart, ['quietZone', 'street', 'toonInterior']), State('street', self.enterStreet, self.exitStreet, ['quietZone']), State('toonInterior', self.enterToonInterior, self.exitToonInterior, ['quietZone']), State('suitInterior', self.enterSuitInterior, self.exitSuitInterior, ['quietZone']), State('quietZone', self.enterQuietZone, self.exitQuietZone, ['street', 'toonInterior', 'suitInterior']), State('final', self.enterFinal, self.exitFinal, ['start']) ], 'start', 'final') self.branchZone = None self.canonicalBranchZone = None self.placeDoneEvent = 'placeDone' self.streetSong = '' self.interiorSong = '' self.linkTunnels = [] self.place = None return def findAndMakeLinkTunnels(self, requestStatus): for tunnel in self.geom.findAllMatches('**/*linktunnel*'): dnaRootStr = tunnel.getName() zone = LinkTunnel.getZoneFromDNARootStr(dnaRootStr) zone = LinkTunnel.maybeFixZone(zone) tunnelClass = LinkTunnel.getRecommendedTunnelClassFromZone(zone) link = tunnelClass(tunnel, dnaRootStr) self.linkTunnels.append(link) def load(self, zoneId): StateData.load(self) self.zoneId = zoneId self.branchZone = ZoneUtil.getBranchZone(zoneId) self.canonicalBranchZone = ZoneUtil.getCanonicalBranchZone(zoneId) def unload(self): self.parentFSMState.removeChild(self.fsm) del self.parentFSMState del self.fsm del self.streetClass base.disablePhysicsNodes(self.landmarkBlocks) self.landmarkBlocks.removeNode() del self.landmarkBlocks self.hood.dnaStore.resetSuitPoints() self.hood.dnaStore.resetBattleCells() del self.hood del self.nodeDict del self.zoneDict del self.fadeInDict del self.fadeOutDict del self.nodeList del self.zoneVisDict base.disablePhysicsNodes(self.geom) self.geom.removeNode() del self.geom del self.streetSong del self.interiorSong #CIGlobals.doSceneCleanup() StateData.unload(self) def enter(self, requestStatus): StateData.enter(self) self.findAndMakeLinkTunnels(requestStatus) self.fsm.enterInitialState() self.setState(requestStatus['where'], requestStatus) def exit(self): self.fsm.requestFinalState() self.ignoreAll() ModelPool.garbageCollect() TexturePool.garbageCollect() StateData.exit(self) def setState(self, state, requestStatus): self.fsm.request(state, [requestStatus]) def enterStart(self): pass def exitStart(self): pass def enterStreet(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.streetDone) self.place = self.streetClass(self, self.fsm, self.placeDoneEvent) self.place.load() def exitStreet(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def streetDone(self): self.requestStatus = self.place.doneStatus status = self.place.doneStatus if (status['loader'] == 'townLoader' and ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone and status['shardId'] is None or status['how'] == 'doorOut' or status['where'] == 'suitInterior'): self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) def enterToonInterior(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.handleToonInteriorDone) self.place = ToonInterior.ToonInterior(self, self.fsm, self.placeDoneEvent) self.place.load() def exitToonInterior(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) return def enterSuitInterior(self, requestStatus): self.acceptOnce(self.placeDoneEvent, self.handleSuitInteriorDone) self.place = CogOfficeInterior.CogOfficeInterior( self, self.fsm, self.placeDoneEvent) self.place.load() def exitSuitInterior(self): self.ignore(self.placeDoneEvent) self.place.exit() self.place.unload() self.place = None base.cr.playGame.setPlace(self.place) def enterThePlace(self, requestStatus): base.cr.playGame.setPlace(self.place) if self.place is not None: self.place.enter(requestStatus) def handleToonInteriorDone(self): status = self.place.doneStatus if (status['loader'] == 'townLoader' and ZoneUtil.getBranchZone(status['zoneId']) == self.branchZone and status['shardId'] is None or status['how'] == 'doorOut'): self.fsm.request('quietZone', [status]) else: self.doneStatus = status messenger.send(self.doneEvent) return def handleSuitInteriorDone(self): self.handleToonInteriorDone() def enterQuietZone(self, requestStatus): self.fsm.request(requestStatus['where'], [requestStatus], exitCurrent=0) self.quietZoneDoneEvent = uniqueName('quietZoneDone') self.acceptOnce(self.quietZoneDoneEvent, self.handleQuietZoneDone) self.quietZoneStateData = QuietZoneState(self.quietZoneDoneEvent) self.quietZoneStateData.load() self.quietZoneStateData.enter(requestStatus) def exitQuietZone(self): self.ignore(self.quietZoneDoneEvent) del self.quietZoneDoneEvent self.quietZoneStateData.exit() self.quietZoneStateData.unload() self.quietZoneStateData = None return def handleQuietZoneDone(self): status = self.quietZoneStateData.getRequestStatus() self.exitQuietZone() self.enterThePlace(status) def enterFinal(self): pass def exitFinal(self): pass def createHood(self, dnaFile, loadStorage=1, flattenNow=True): if loadStorage: loader.loadDNAFile(self.hood.dnaStore, 'phase_5/dna/storage_town.pdna') loader.loadDNAFile(self.hood.dnaStore, self.townStorageDNAFile) node = loader.loadDNAFile(self.hood.dnaStore, dnaFile) if node.getNumParents() == 1: self.geom = NodePath(node.getParent(0)) self.geom.reparentTo(hidden) else: self.geom = hidden.attachNewNode(node) if flattenNow: self.doFlatten() self.geom.setName('town_top_level') def doFlatten(self): self.makeDictionaries(self.hood.dnaStore) self.reparentLandmarkBlockNodes() base.createPhysicsNodes(self.geom) self.renameFloorPolys(self.nodeList) self.geom.flattenLight() CIGlobals.preRenderScene(self.geom) def reparentLandmarkBlockNodes(self): bucket = self.landmarkBlocks = hidden.attachNewNode('landmarkBlocks') npc = self.geom.findAllMatches('**/sb*:*_landmark_*_DNARoot') for i in xrange(npc.getNumPaths()): nodePath = npc.getPath(i) nodePath.wrtReparentTo(bucket) npc = self.geom.findAllMatches('**/sb*:*animated_building*_DNARoot') for i in xrange(npc.getNumPaths()): nodePath = npc.getPath(i) nodePath.wrtReparentTo(bucket) def makeDictionaries(self, dnaStore): self.nodeDict = {} self.zoneDict = {} self.zoneVisDict = {} self.nodeList = [] self.fadeInDict = {} self.fadeOutDict = {} a1 = Vec4(1, 1, 1, 1) a0 = Vec4(1, 1, 1, 0) numVisGroups = dnaStore.getNumDNAVisGroupsAI() for i in xrange(numVisGroups): groupFullName = dnaStore.getDNAVisGroupName(i) visGroup = dnaStore.getDNAVisGroupAI(i) groupName = base.cr.hoodMgr.extractGroupName(groupFullName) zoneId = int(groupName) zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId) groupNode = self.geom.find('**/' + groupFullName) if groupNode.isEmpty(): continue else: if ':' in groupName: groupName = '%s%s' % (zoneId, groupName[groupName.index(':'):]) else: groupName = '%s' % zoneId groupNode.setName(groupName) CIGlobals.replaceDecalEffectsWithDepthOffsetAttrib(groupNode) #group all the flat walls block2flatwall = {} flatwalls = groupNode.findAllMatches("**/tb*:*_DNARoot;+s") for flatwall in flatwalls: if "toon_landmark" in flatwall.getName(): print "Skipping", flatwall.getName() continue if flatwall.hasTag("DNACode") and flatwall.hasMat(): continue block = int(flatwall.getName().split(":")[0][2:]) if not block2flatwall.has_key(block): block2flatwall[block] = groupNode.attachNewNode( ModelNode('toonBuildingsBlock' + str(block))) flatwall.wrtReparentTo(block2flatwall[block]) for node in block2flatwall.values(): for child in node.findAllMatches("**"): child.clearEffect(DecalEffect.getClassType()) child.clearTag("DNACode") child.clearTag("cam") CIGlobals.clearModelNodesBelow(node) node.flattenStrong() flattenGroup = groupNode.attachNewNode('optim') flattens = ['street*_DNARoot'] removes = ['interactive_prop*_DNARoot'] for remove in removes: for np in groupNode.findAllMatches("**/" + remove): np.removeNode() for flatten in flattens: for np in groupNode.findAllMatches("**/" + flatten): if np.hasTag("DNACode") and np.hasMat(): continue for child in np.findAllMatches("**"): child.clearEffect(DecalEffect.getClassType()) child.clearTag("DNACode") child.clearTag("cam") np.wrtReparentTo(flattenGroup) flattenGroup.clearModelNodes() flattenGroup.flattenStrong() CIGlobals.flattenModelNodes(groupNode) groupNode.flattenStrong() #groupNode.ls() self.nodeDict[zoneId] = [] self.nodeList.append(groupNode) self.zoneDict[zoneId] = groupNode visibles = [] for i in xrange(visGroup.getNumVisibles()): visibles.append(int(visGroup.get_visible(i))) visibles.append(ZoneUtil.getBranchZone(zoneId)) self.zoneVisDict[zoneId] = visibles fadeDuration = 0.5 self.fadeOutDict[groupNode] = Sequence( Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a0, startColorScale=a1), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), Func(groupNode.stash), Func(base.disablePhysicsNodes, groupNode), name='fadeZone-' + str(zoneId), autoPause=1) self.fadeInDict[groupNode] = Sequence( Func(base.enablePhysicsNodes, groupNode), Func(groupNode.unstash), Func(groupNode.setTransparency, 1), LerpColorScaleInterval(groupNode, fadeDuration, a1, startColorScale=a0), Func(groupNode.clearColorScale), Func(groupNode.clearTransparency), name='fadeZone-' + str(zoneId), autoPause=1) for i in xrange(numVisGroups): groupFullName = dnaStore.getDNAVisGroupName(i) zoneId = int(base.cr.hoodMgr.extractGroupName(groupFullName)) zoneId = ZoneUtil.getTrueZoneId(zoneId, self.zoneId) for j in xrange(dnaStore.getNumVisiblesInDNAVisGroup(i)): visName = dnaStore.getVisibleName(i, j) groupName = base.cr.hoodMgr.extractGroupName(visName) nextZoneId = int(groupName) nextZoneId = ZoneUtil.getTrueZoneId(nextZoneId, self.zoneId) visNode = self.zoneDict[nextZoneId] self.nodeDict[zoneId].append(visNode) self.hood.dnaStore.resetPlaceNodes() self.hood.dnaStore.resetDNAGroups() self.hood.dnaStore.resetDNAVisGroups() self.hood.dnaStore.resetDNAVisGroupsAI() def renameFloorPolys(self, nodeList): for i in nodeList: collNodePaths = i.findAllMatches('**/+BulletRigidBodyNode') numCollNodePaths = collNodePaths.getNumPaths() visGroupName = i.node().getName() for j in xrange(numCollNodePaths): collNodePath = collNodePaths.getPath(j) bitMask = collNodePath.node().getIntoCollideMask() if bitMask == CIGlobals.FloorGroup: collNodePath.node().setName(visGroupName) collNodePath.setCollideMask(CIGlobals.StreetVisGroup)
class cMinicolumn: def __init__(self, nameOfLayer, nOfCellsPerColumn): self.cells = [] self.nOfCellsPerColumn = nOfCellsPerColumn for i in range(nOfCellsPerColumn): n = cCell(self) self.cells.append(n) self.idx = -1 self.parentLayer = nameOfLayer self.transparency = 1.0 self.gfxCreated = False self.LodDistance1Stored = 100.0 self.LodDistance2Stored = 5000.0 self.bursting = False self.active = False self.oneOfCellPredictive = False self.oneOfCellCorrectlyPredicted = False self.oneOfCellFalselyPredicted = False self.cntSegments = None # info about how many segments are on this cell def CreateGfx(self, loader, idx): # __node # / \ # cellsNodePath columnBox self.lod = LODNode("columnLOD") # Level of detail node for Column self.__node = NodePath( self.lod ) # NodePath(PandaNode('column'))# loader.loadModel("models/box") self.__node.setPos(0, 0, 0) self.__node.setScale(1, 1, 1) self.idx = idx # self.__node.setTag('clickable',str(idx))#to be able to click on it self.__columnBox = loader.loadModel( os.path.join(os.getcwd(), "models/cube")) self.__columnBox.setPos( 0, 0, -0.5 + (0 if len(self.cells) == 0 else len(self.cells) * (1 + CELL_OFFSET) / 2)) self.__columnBox.setScale( 0.5, 0.5, 0.5 * (1 if len(self.cells) == 0 else len(self.cells) * (1 + CELL_OFFSET))) self.__columnBox.setName("columnBox") self.__cellsNodePath = NodePath( PandaNode("cellsNode")) # to pack all cells into one node path self.__cellsNodePath.setName("column") self.__cellsNodePath.setTag( "id", str(idx)) # to be able to retrieve index of column for mouse click self.lod.addSwitch(100.0, 0.0) self.lod.addSwitch(5000.0, 100.0) self.__cellsNodePath.reparentTo(self.__node) self.__columnBox.reparentTo(self.__node) z = 0 idx = 0 for n in self.cells: n.CreateGfx(loader, idx) idx += 1 n.getNode().setPos(0, 0, z) z += 1 + CELL_OFFSET n.getNode().reparentTo(self.__cellsNodePath) self.gfxCreated = True def LODUpdateSwitch(self, lodDistance, lodDistance2): self.lodDistance1Stored = lodDistance self.lodDistance2Stored = lodDistance2 self.lod.clearSwitches() self.lod.addSwitch(lodDistance, 0.0) self.lod.addSwitch(lodDistance2, lodDistance) def LODUpdateSwitch_long(self): self.lod.clearSwitches() self.lod.addSwitch(self.lodDistance2Stored, 0.0) self.lod.addSwitch(self.lodDistance2Stored, self.lodDistance2Stored) def LODUpdateSwitch_normal(self): self.LODUpdateSwitch(self.lodDistance1Stored, self.lodDistance2Stored) def UpdateState(self, bursting, activeColumn, oneOfCellPredictive, oneOfCellCorrectlyPredicted, oneOfCellFalselyPredicted): self.bursting = bursting self.active = activeColumn self.oneOfCellPredictive = oneOfCellPredictive self.oneOfCellCorrectlyPredicted = oneOfCellCorrectlyPredicted self.oneOfCellFalselyPredicted = oneOfCellFalselyPredicted # update column box color (for LOD in distance look) if self.oneOfCellCorrectlyPredicted: COL_COLUMN_ONEOFCELLCORRECTLY_PREDICTED.setW(self.transparency) col = COL_COLUMN_ONEOFCELLCORRECTLY_PREDICTED self.__columnBox.setColor(col) elif self.oneOfCellFalselyPredicted: COL_COLUMN_ONEOFCELLFALSELY_PREDICTED.setW(self.transparency) col = COL_COLUMN_ONEOFCELLFALSELY_PREDICTED self.__columnBox.setColor(col) elif self.bursting: COL_COLUMN_BURSTING.setW(self.transparency) col = COL_COLUMN_BURSTING self.__columnBox.setColor(col) elif self.active and self.oneOfCellPredictive: COL_COLUMN_ACTIVE_AND_ONEOFCELLPREDICTIVE.setW(self.transparency) col = COL_COLUMN_ACTIVE_AND_ONEOFCELLPREDICTIVE self.__columnBox.setColor(col) elif self.oneOfCellPredictive: COL_COLUMN_ONEOFCELLPREDICTIVE.setW(self.transparency) col = COL_COLUMN_ONEOFCELLPREDICTIVE self.__columnBox.setColor(col) elif self.active: COL_COLUMN_ACTIVE.setW(self.transparency) col = COL_COLUMN_ACTIVE self.__columnBox.setColor(col) else: COL_COLUMN_INACTIVE.setW(self.transparency) col = COL_COLUMN_INACTIVE self.__columnBox.setColor(col) # for n in self.cells: # n.active = active # n.UpdateState() def getNode(self): return self.__node def updateWireframe(self, value): for cell in self.cells: cell.updateWireframe(value) if value: self.__columnBox.setRenderModeFilledWireframe(LColor(0, 0, 0, 1.0)) else: self.__columnBox.setRenderModeFilled() def CreateSynapses(self, regionObjects, columnConnections, synapsesType, sourceRegions, activeOnly): printLog("Creating synapses", verbosityMedium) ConnectionFactory.CreateSynapses( callbackCreateSynapse=self._CreateOneSynapse, synapsesType=synapsesType, regionObjects=regionObjects, connections=columnConnections, idx=self.idx, sourceRegions=sourceRegions, activeOnly=activeOnly) for arr in columnConnections: if arr[0] == self.idx: # find this column self.cntSegments = len(arr[1]) break # creates synapse, that will go from presynCell to this cell # presynCell - cell object def _CreateOneSynapse(self, presynCell, synapsesType): form = GeomVertexFormat.getV3() vdata = GeomVertexData("SynapseLine", form, Geom.UHStatic) vdata.setNumRows(1) vertex = GeomVertexWriter(vdata, "vertex") vertex.addData3f(presynCell.getNode().getPos(self.__node)) vertex.addData3f(0, 0, 0) # vertex.addData3f(self.__node.getPos()) # printLog("inputObj:"+str(i)+"bits:"+str(y)) # printLog(inputObj[i].inputBits[y].getNode().getPos(self.__node)) prim = GeomLines(Geom.UHStatic) prim.addVertices(0, 1) geom = Geom(vdata) geom.addPrimitive(prim) node = GeomNode("Synapse_" + str(synapsesType)) node.addGeom(geom) nodePath = self.__cellsNodePath.attachNewNode(node) nodePath.setRenderModeThickness(2) # color of the line if presynCell.active: nodePath.setColor(COL_PROXIMAL_SYNAPSES_ACTIVE) else: nodePath.setColor(COL_PROXIMAL_SYNAPSES_INACTIVE) def setTransparency(self, transparency): self.transparency = transparency for cell in self.cells: cell.setTransparency(transparency) self.UpdateState(self.bursting, self.active, self.oneOfCellPredictive, self.oneOfCellCorrectlyPredicted, self.oneOfCellFalselyPredicted) def DestroySynapses(self, synapseType=None): if synapseType is None: synapseType = '*' if not self.gfxCreated: return if synapseType == 'proximal': for syn in self.__cellsNodePath.findAllMatches("Synapse_" + str(synapseType)): syn.removeNode() for cell in self.cells: cell.DestroySynapses(synapseType) def getDescription(self): txt = "" txt += "ID:" + str(self.idx) + "\n" txt += "Active:" + str(self.active) + "\n" txt += "One of cell is predictive:" + str( self.oneOfCellPredictive) + "\n" txt += "One of cell correctly predicted:" + str( self.oneOfCellCorrectlyPredicted) + "\n" txt += "One of cell false predicted:" + str( self.oneOfCellFalselyPredicted) + "\n" txt += "Number of segments:" + str(self.cntSegments) + "\n" return txt
class CogdoMazeFactory: def __init__(self, randomNumGen, width, height, frameWallThickness = Globals.FrameWallThickness, cogdoMazeData = CogdoMazeData): self._rng = RandomNumGen(randomNumGen) self.width = width self.height = height self.frameWallThickness = frameWallThickness self._cogdoMazeData = cogdoMazeData self.quadrantSize = self._cogdoMazeData.QuadrantSize self.cellWidth = self._cogdoMazeData.QuadrantCellWidth def getMazeData(self): if not hasattr(self, '_data'): self._generateMazeData() return self._data def createCogdoMaze(self, flattenModel = True): if not hasattr(self, '_maze'): self._loadAndBuildMazeModel(flatten=flattenModel) return CogdoMaze(self._model, self._data, self.cellWidth) def _gatherQuadrantData(self): self.openBarriers = [] barrierItems = range(Globals.TotalBarriers) self._rng.shuffle(barrierItems) for i in barrierItems[0:len(barrierItems) - Globals.NumBarriers]: self.openBarriers.append(i) self.quadrantData = [] quadrantKeys = self._cogdoMazeData.QuadrantCollisions.keys() self._rng.shuffle(quadrantKeys) i = 0 for y in xrange(self.height): for x in xrange(self.width): key = quadrantKeys[i] collTable = self._cogdoMazeData.QuadrantCollisions[key] angle = self._cogdoMazeData.QuadrantAngles[self._rng.randint(0, len(self._cogdoMazeData.QuadrantAngles) - 1)] self.quadrantData.append((key, collTable[angle], angle)) i += 1 if x * y >= self._cogdoMazeData.NumQuadrants: i = 0 def _generateBarrierData(self): data = [] for y in xrange(self.height): data.append([]) for x in xrange(self.width): if x == self.width - 1: ax = -1 else: ax = 1 if y == self.height - 1: ay = -1 else: ay = 1 data[y].append([ax, ay]) dirUp = 0 dirDown = 1 dirLeft = 2 dirRight = 3 def getAvailableDirections(ax, ay, ignore = None): dirs = [] if ax - 1 >= 0 and data[ay][ax - 1][BARRIER_DATA_RIGHT] == 1 and (ax, ay) != ignore: dirs.append(dirLeft) if ax + 1 < self.width and data[ay][ax][BARRIER_DATA_RIGHT] == 1 and (ax, ay) != ignore: dirs.append(dirRight) if ay - 1 >= 0 and data[ay - 1][ax][BARRIER_DATA_TOP] == 1 and (ax, ay) != ignore: dirs.append(dirDown) if ay + 1 < self.height and data[ay][ax][BARRIER_DATA_TOP] == 1 and (ax, ay) != ignore: dirs.append(dirUp) return dirs visited = [] def tryVisitNeighbor(ax, ay, ad): if ad == dirUp: if data[ay][ax] in visited: return None visited.append(data[ay][ax]) data[ay][ax][BARRIER_DATA_TOP] = 0 ay += 1 elif ad == dirDown: if data[ay - 1][ax] in visited: return None visited.append(data[ay - 1][ax]) data[ay - 1][ax][BARRIER_DATA_TOP] = 0 ay -= 1 elif ad == dirLeft: if data[ay][ax - 1] in visited: return None visited.append(data[ay][ax - 1]) data[ay][ax - 1][BARRIER_DATA_RIGHT] = 0 ax -= 1 elif ad == dirRight: if data[ay][ax] in visited: return None visited.append(data[ay][ax]) data[ay][ax][BARRIER_DATA_RIGHT] = 0 ax += 1 return (ax, ay) def openBarriers(x, y): dirs = getAvailableDirections(x, y) for dir in dirs: next = tryVisitNeighbor(x, y, dir) if next is not None: openBarriers(*next) return x = self._rng.randint(0, self.width - 1) y = self._rng.randint(0, self.height - 1) openBarriers(x, y) self._barrierData = data return def _generateMazeData(self): if not hasattr(self, 'quadrantData'): self._gatherQuadrantData() self._data = {} self._data['width'] = (self.width + 1) * self.frameWallThickness + self.width * self.quadrantSize self._data['height'] = (self.height + 1) * self.frameWallThickness + self.height * self.quadrantSize self._data['originX'] = int(self._data['width'] / 2) self._data['originY'] = int(self._data['height'] / 2) collisionTable = [] horizontalWall = [ 1 for x in xrange(self._data['width']) ] collisionTable.append(horizontalWall) for i in xrange(0, len(self.quadrantData), self.width): for y in xrange(self.quadrantSize): row = [1] for x in xrange(i, i + self.width): if x == 1 and y < self.quadrantSize / 2 - 2: newData = [] for j in self.quadrantData[x][1][y]: if j == 0: newData.append(2) else: newData.append(j + 0) row += newData + [1] else: row += self.quadrantData[x][1][y] + [1] collisionTable.append(row) collisionTable.append(horizontalWall[:]) barriers = Globals.MazeBarriers for i in xrange(len(barriers)): for coords in barriers[i]: collisionTable[coords[1]][coords[0]] = 0 y = self._data['originY'] for x in xrange(len(collisionTable[y])): if collisionTable[y][x] == 0: collisionTable[y][x] = 2 x = self._data['originX'] for y in xrange(len(collisionTable)): if collisionTable[y][x] == 0: collisionTable[y][x] = 2 self._data['collisionTable'] = collisionTable def _loadAndBuildMazeModel(self, flatten = False): self.getMazeData() self._model = NodePath('CogdoMazeModel') levelModel = CogdoUtil.loadMazeModel('level') self.quadrants = [] quadrantUnitSize = int(self.quadrantSize * self.cellWidth) frameActualSize = self.frameWallThickness * self.cellWidth size = quadrantUnitSize + frameActualSize halfWidth = int(self.width / 2) halfHeight = int(self.height / 2) i = 0 for y in xrange(self.height): for x in xrange(self.width): ax = (x - halfWidth) * size ay = (y - halfHeight) * size extension = '' if hasattr(getBase(), 'air'): extension = '.bam' filepath = self.quadrantData[i][0] + extension angle = self.quadrantData[i][2] m = self._createQuadrant(filepath, i, angle, quadrantUnitSize) m.setPos(ax, ay, 0) m.reparentTo(self._model) self.quadrants.append(m) i += 1 quadrantHalfUnitSize = quadrantUnitSize * 0.5 barrierModel = CogdoUtil.loadMazeModel('grouping_blockerDivider').find('**/divider') y = 3 for x in xrange(self.width): if x == (self.width - 1) / 2: continue ax = (x - halfWidth) * size ay = (y - halfHeight) * size - quadrantHalfUnitSize - (self.cellWidth - 0.5) b = NodePath('barrier') barrierModel.instanceTo(b) b.setPos(ax, ay, 0) b.reparentTo(self._model) offset = self.cellWidth - 0.5 for x in (0, 3): for y in xrange(self.height): ax = (x - halfWidth) * size - quadrantHalfUnitSize - frameActualSize + offset ay = (y - halfHeight) * size b = NodePath('barrier') barrierModel.instanceTo(b) b.setPos(ax, ay, 0) b.setH(90) b.reparentTo(self._model) offset -= 2.0 barrierModel.removeNode() levelModel.getChildren().reparentTo(self._model) for np in self._model.findAllMatches('**/*lightCone*'): CogdoUtil.initializeLightCone(np, 'fixed', 3) if flatten: self._model.flattenStrong() return self._model def _createQuadrant(self, filepath, serialNum, angle, size): root = NodePath('QuadrantRoot-%i' % serialNum) quadrant = loader.loadModel(filepath) quadrant.getChildren().reparentTo(root) root.setH(angle) return root
class GunGameLevelLoader: notify = directNotify.newCategory("GunGameLevelLoader") LevelData = { # momada means: Mix Of Mint And District Attorney's 'momada': { 'name': ZoneUtil.ToonBattleOriginalLevel, 'camera': (Point3(0.0, -25.80, 7.59), Vec3(0.00, 0.00, 0.00)), 'models': [ "phase_11/models/lawbotHQ/LB_Zone03a.bam", "phase_11/models/lawbotHQ/LB_Zone04a.bam", "phase_11/models/lawbotHQ/LB_Zone7av2.bam", "phase_11/models/lawbotHQ/LB_Zone08a.bam", "phase_11/models/lawbotHQ/LB_Zone13a.bam", "phase_10/models/cashbotHQ/ZONE17a.bam", "phase_10/models/cashbotHQ/ZONE18a.bam", "phase_11/models/lawbotHQ/LB_Zone22a.bam" ], 'parents': [ render, "EXIT", "EXIT", "EXIT", "ENTRANCE", "ENTRANCE", "ENTRANCE", "EXIT" ], 'model_positions': [ Point3(0.00, 0.00, 0.00), Point3(-1.02, 59.73, 0.00), Point3(0.00, 74.77, 0.00), Point3(0.00, 89.37, -13.50), Point3(16.33, -136.53, 0.00), Point3(-1.01, -104.40, 0.00), Point3(0.65, -23.86, 0.00), Point3(-55.66, -29.01, 0.00) ], 'model_orientations': [ Vec3(0.00, 0.00, 0.00), Vec3(0.00, 0.00, 0.00), Vec3(90.00, 0.00, 0.00), Vec3(180.00, 0.00, 0.00), Vec3(97.00, 0.00, 0.00), Vec3(359.95, 0.00, 0.00), Vec3(90.00, 0.00, 0.00), Vec3(270.00, 0.00, 0.00) ], 'spawn_points': [ (Point3(0, 0, 0), Vec3(0, 0, 0)), (Point3(-20, 50, 0), Vec3(0, 0, 0)), (Point3(20, 50, 0), Vec3(0, 0, 0)), (Point3(0, 120, 0), Vec3(0, 0, 0)), (Point3(0, 100, 0), Vec3(180, 0, 0)), (Point3(-90, 0, 0), Vec3(0, 0, 0)), (Point3(-170, 0, 0), Vec3(0, 0, 0)), (Point3(-90, 50, 0), Vec3(0, 0, 0)), (Point3(-170, 50, 0), Vec3(0, 0, 0)), (Point3(35, 250, 0), Vec3(-90, 0, 0)), (Point3(0, 285, 0), Vec3(180, 0, 0)), (Point3(-185, 250, 0), Vec3(90, 0, 0)) ] }, 'dg': { 'name': ZoneUtil.DaisyGardens, 'camera': (Point3(-33.13, -3.20, 48.62), Vec3(326.31, 332.68, 0.00)), 'dna': [ 'phase_8/dna/storage_DG.pdna', 'phase_8/dna/storage_DG_sz.pdna', 'phase_8/dna/daisys_garden_sz.pdna' ], 'sky': 'TT', 'spawn_points': hoodMgr.dropPoints[ZoneUtil.DaisyGardens] }, 'mml': { 'name': ZoneUtil.MinniesMelodyland, 'camera': (Point3(-54.42, -91.05, 34.89), Vec3(315.29, 336.80, 0.00)), 'dna': [ 'phase_6/dna/storage_MM.pdna', 'phase_6/dna/storage_MM_sz.pdna', 'phase_6/dna/minnies_melody_land_sz.pdna' ], 'sky': 'MM', 'spawn_points': hoodMgr.dropPoints[ZoneUtil.MinniesMelodyland] }, 'oz': { 'name': ZoneUtil.OutdoorZone, 'camera': (Point3(-54.42, -91.05, 34.89), Vec3(315.29, 336.80, 0.00)), 'dna': [ 'phase_6/dna/storage_OZ.pdna', 'phase_6/dna/storage_OZ_sz.pdna', 'phase_6/dna/outdoor_zone_sz.pdna' ], 'sky': 'TT', 'spawn_points': hoodMgr.dropPoints[ZoneUtil.OutdoorZone] }, 'cbhq': { 'name': ZoneUtil.CashbotHQ, 'camera': (Point3(302.64, 5.00, 15.20), Vec3(135.00, 341.57, 0.00)), 'model': 'phase_10/models/cogHQ/CashBotShippingStation.bam', 'sky': None, 'spawn_points': hoodMgr.dropPoints[ZoneUtil.CashbotHQ] }, 'sbf': { 'name': ZoneUtil.SellbotFactory, 'camera': (Point3(0, 0, 0), Vec3(0, 0, 0)), 'model': "phase_9/models/cogHQ/SelbotLegFactory.bam", 'sky': 'cog', 'sky_scale': 10.0, 'occluders': 'phase_9/models/cogHQ/factory_sneak_occluders.egg', 'spawn_points': {GGG.Teams.BLUE: [ (Point3(13, 30, 3.73), Point3(0, 0, 0)), (Point3(21, 30, 3.73), Point3(0, 0, 0)), (Point3(29, 30, 3.73), Point3(0, 0, 0)), (Point3(13, 20, 3.73), Point3(0, 0, 0)), (Point3(21, 20, 3.73), Point3(0, 0, 0)), (Point3(29, 30, 3.73), Point3(0, 0, 0))], GGG.Teams.RED: [ (Point3(-644.43, 378.12, 8.73), Point3(270, 0, 0)), (Point3(-644.43, 370.75, 8.73), Point3(270, 0, 0)), (Point3(-644.43, 363.22, 8.73), Point3(270, 0, 0)), (Point3(-659.05, 378.12, 8.73), Point3(270, 0, 0)), (Point3(-659.05, 370.75, 8.73), Point3(270, 0, 0)), (Point3(-659.05, 363.22, 8.73), Point3(270, 0, 0))] }, 'flag_points': {GGG.Teams.BLUE: [Point3(213.23, 340.59, 19.73), Point3(90, 0, 0)], GGG.Teams.RED: [Point3(-543.60, 595.79, 9.73), Point3(270, 0, 0)]}, 'flagpoint_points': {GGG.Teams.BLUE: [Point3(-543.60, 595.79, 9.73), Point3(270, 0, 0)], GGG.Teams.RED: [Point3(213.23, 340.59, 19.73), Point3(0, 0, 0)]} }, 'ttc' : { 'name' : ZoneUtil.ToontownCentral, 'dna' : [ 'phase_4/dna/storage_TT.pdna', 'phase_4/dna/storage_TT_sz.pdna', 'phase_4/dna/new_ttc_sz.pdna', ], 'sky' : 'TT', 'spawn_points' : [ (9.90324401855, 91.9139556885, 8.0364112854, -545.909545898, 0.0, 0.0), (77.9181442261, 50.953086853, 7.52815723419, -598.509460449, 0.0, 0.0), (93.7379760742, 6.37303066254, 7.99749088287, -626.209533691, 0.0, 0.0), (39.0383415222, -81.5989837646, 8.01874637604, -694.309265137, 0.0, 0.0), (-19.2093048096, -95.1359481812, 8.07303524017, -731.409240723, 0.0, 0.0), (-84.4093933105, -45.4780502319, 8.06541728973, -781.809143066, 0.0, 0.0), (-92.2512283325, 2.41426730156, 8.03108692169, -811.70916748, 0.0, 0.0), (46.8868179321, 81.3593673706, 8.04793071747, -955.309509277, 0.0, 0.0), (32.3203735352, 90.0017929077, 8.06353855133, -884.409301758, 0.0, 0.0) ], 'cap_point' : Point3(-1.5, 0, 0) } } SkyData = { 'TT': 'phase_3.5/models/props', 'MM': 'phase_6/models/props', 'cog': 'phase_9/models/cogHQ', 'MovingSkies': ['TT'] } def __init__(self, mg): self.mg = mg self.levelName = None self.dnaStore = DNAStorage() self.loadingText = None # for not momada only: self.levelGeom = None self.olc = None self.occluders = None # for momada only: self.momadaAreas = [] self.momadaAreaName2areaModel = {} def getFlagPoint_Point(self, team): return self.LevelData[self.levelName]['flagpoint_points'][team] def getFlagPoint(self, team): return self.LevelData[self.levelName]['flag_points'][team] def getCapturePoint(self): return self.LevelData[self.levelName]['cap_point'] def setLevel(self, level): self.levelName = level def getLevel(self): return self.levelName def getCameraOfCurrentLevel(self): return self.LevelData[self.getLevel()]['camera'] def getSpawnPoints(self): # Return the spawn points for this level. pointData = self.LevelData[self.levelName]['spawn_points'] if self.levelName == "momada": return pointData else: if self.mg.gameMode in [GGG.GameModes.CASUAL, GGG.GameModes.KOTH]: # These points come from src.coginvasion.distributed.HoodMgr, # which is a tuple of a bunch of arrays with pos as first # 3, and hpr as last 3 list elements. # # Disect the arrays and return a tuple holding a Point3 pos, and a Vec3 hpr. array = [] for posAndHpr in pointData: array.append( ( Point3( posAndHpr[0], posAndHpr[1], posAndHpr[2] ), Vec3( posAndHpr[3], posAndHpr[4], posAndHpr[5] ) ) ) elif self.mg.gameMode == GGG.GameModes.CTF: array = pointData[self.mg.team] return array def getNameOfCurrentLevel(self): return self.LevelData[self.getLevel()]['name'] def load(self): self.unload() if self.loadingText: self.loadingText.destroy() self.loadingText = None self.loadingText = OnscreenText(text = "", font = CIGlobals.getMinnieFont(), fg = (1, 1, 1, 1)) self.loadingText.setBin('gui-popup', 0) base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() if self.levelName == "momada": # momada is completely different from the other levels, # so it has it's own separate method for loading. self.__momadaLoad() elif self.levelName in ['cbhq', 'sbf']: # Cog hqs are just one model with everything in it. no dna loading needed. modelPath = self.LevelData[self.levelName]['model'] self.levelGeom = loader.loadModel(modelPath) self.levelGeom.flattenMedium() self.levelGeom.reparentTo(render) if self.LevelData[self.levelName].get('occluders'): self.occluders = loader.loadModel(self.LevelData[self.levelName]['occluders']) for occluderNode in self.occluders.findAllMatches('**/+OccluderNode'): base.render.setOccluder(occluderNode) occluderNode.node().setDoubleSided(True) if self.levelName == 'sbf': base.camLens.setFar(250) else: # It's a playground with dna and stuff. Just do the # normal loading procedure. dnaFiles = self.LevelData[self.levelName]['dna'] loadDNAFile(self.dnaStore, 'phase_4/dna/storage.pdna') for index in range(len(dnaFiles)): if index == len(dnaFiles) - 1: node = loadDNAFile(self.dnaStore, dnaFiles[index]) if node.getNumParents() == 1: self.levelGeom = NodePath(node.getParent(0)) self.levelGeom.reparentTo(hidden) else: self.levelGeom = hidden.attachNewNode(node) if self.levelName == 'ttc' and dnaFiles[index] == 'phase_4/dna/new_ttc_sz.pdna': self.levelGeom.find('**/prop_gazebo_DNARoot').removeNode() else: self.levelGeom.flattenMedium() gsg = base.win.getGsg() if gsg: self.levelGeom.prepareScene(gsg) self.levelGeom.reparentTo(render) else: loadDNAFile(self.dnaStore, dnaFiles[index]) children = self.levelGeom.findAllMatches('**/*doorFrameHole*') for child in children: child.hide() self.olc = ZoneUtil.getOutdoorLightingConfig(self.LevelData[self.levelName].get('name')) self.olc.setupAndApply() if self.loadingText: self.loadingText.destroy() self.loadingText = None def __momadaLoad(self): def attachArea(itemNum): name = 'MomadaArea-%s' % itemNum area = self.momadaAreaName2areaModel.get(name) parents = self.LevelData['momada']['parents'] parent = parents[itemNum] if type(parent) == type(""): parent = self.momadaAreas[itemNum - 1].find('**/' + parent) pos = self.LevelData['momada']['model_positions'][itemNum] hpr = self.LevelData['momada']['model_orientations'][itemNum] area.reparentTo(parent) area.setPos(pos) area.setHpr(hpr) _numItems = 0 name = None for item in self.LevelData['momada']['models']: name = 'MomadaArea-%s' % _numItems area = loader.loadModel(item) self.momadaAreas.append(area) self.momadaAreaName2areaModel[name] = area attachArea(_numItems) _numItems += 1 self.notify.info("Loaded and attached %s momada areas." % _numItems) def unload(self): render.clearOccluder() if self.olc: self.olc.cleanup() self.olc = None if self.levelName == "sbf": base.camLens.setFar(CIGlobals.DefaultCameraFar) if self.levelName == "momada": for area in self.momadaAreas: self.momadaAreas.remove(area) area.removeNode() del area self.momadaAreas = [] self.momadaAreaName2areaModel = {} else: if self.occluders: self.occluders.removeNode() self.occluders = None if self.levelGeom: self.levelGeom.removeNode() self.levelGeom = None def cleanup(self): self.momadaAreas = None self.momadaAreaName2areaModel = None if self.dnaStore: self.dnaStore.reset_nodes() self.dnaStore.reset_hood_nodes() self.dnaStore.reset_place_nodes() self.dnaStore.reset_hood() self.dnaStore.reset_fonts() self.dnaStore.reset_DNA_vis_groups() self.dnaStore.reset_materials() self.dnaStore.reset_block_numbers() self.dnaStore.reset_block_zones() self.dnaStore.reset_suit_points() self.dnaStore = None
class PopupMenu(DirectObject): ''' A class to create a popup or context menu. Features : [1] it's destroyed by pressing ESCAPE, or LMB/RMB click outside of it [2] menu item's command is executed by pressing ENTER/RETURN or SPACE when it's hilighted [3] you can use arrow UP/DOWN to navigate [4] separator lines [5] menu item image [6] menu item hotkey If there are more than 1 item using the same hotkey, those items will be hilighted in cycle when the hotkey is pressed. [7] shortcut key text at the right side of menu item [8] multiple lines item text [9] menu item can have sub menus [10] it's offscreen-proof, try to put your pointer next to screen edge or corner before creating it ''' grayImages = {} # storage of grayed images, # so the same image will be converted to grayscale only once def __init__(self, items, parent=None, buttonThrower=None, onDestroy=None, font=None, baselineOffset=.0, scale=.05, itemHeight=1., leftPad=.0, separatorHeight=.5, underscoreThickness=1, BGColor=(0, 0, 0, .7), BGBorderColor=(1, .85, .4, 1), separatorColor=(1, 1, 1, 1), frameColorHover=(1, .85, .4, 1), frameColorPress=(0, 1, 0, 1), textColorReady=(1, 1, 1, 1), textColorHover=(0, 0, 0, 1), textColorPress=(0, 0, 0, 1), textColorDisabled=(.5, .5, .5, 1), minZ=None, useMouseZ=True): ''' items : a collection of menu items Item format : ( 'Item text', 'path/to/image', command ) OR ( 'Item text', 'path/to/image', command, arg1,arg2,.... ) If you don't want to use an image, pass 0. To create disabled item, pass 0 for the command : ( 'Item text', 'path/to/image', 0 ) so, you can easily switch between enabled or disabled : ( 'Item text', 'path/to/image', command if commandEnabled else 0 ) OR ( 'Item text', 'path/to/image', (0,command)[commandEnabled] ) To create submenu, pass a sequence of submenu items for the command. To create disabled submenu, pass an empty sequence for the command. To enable hotkey, insert an underscore before the character, e.g. hotkey of 'Item te_xt' is 'x' key. To add shortcut key text at the right side of the item, append it at the end of the item text, separated by "more than" sign, e.g. 'Item text>Ctrl-T'. To insert separator line, pass 0 for the whole item. parent : where to attach the menu, defaults to aspect2d buttonThrower : button thrower whose thrown events are blocked temporarily when the menu is displayed. If not given, the default button thrower is used onDestroy : user function which will be called after the menu is fully destroyed font : text font baselineOffset : text's baseline Z offset scale : text scale itemHeight : spacing between items, defaults to 1 leftPad : blank space width before text separatorHeight : separator line height, relative to itemHeight underscoreThickness : underscore line thickness BGColor, BGBorderColor, separatorColor, frameColorHover, frameColorPress, textColorReady, textColorHover, textColorPress, textColorDisabled are some of the menu components' color minZ : minimum Z position to restrain menu's bottom from going offscreen (-1..1). If it's None, it will be set a little above the screen's bottom. ''' self.parent = parent if parent else aspect2d self.onDestroy = onDestroy self.BT = buttonThrower if buttonThrower else base.buttonThrowers[ 0].node() self.menu = NodePath('menu-%s' % id(self)) self.parentMenu = None self.submenu = None self.BTprefix = self.menu.getName() + '>' self.submenuCreationTaskName = 'createSubMenu-' + self.BTprefix self.submenuRemovalTaskName = 'removeSubMenu-' + self.BTprefix self.font = font if font else TextNode.getDefaultFont() self.baselineOffset = baselineOffset if isinstance(scale, (float, int)): scale = (scale, 1.0, scale) self.scale = scale self.itemHeight = itemHeight self.leftPad = leftPad self.separatorHeight = separatorHeight self.underscoreThickness = underscoreThickness self.BGColor = BGColor self.BGBorderColor = BGBorderColor self.separatorColor = separatorColor self.frameColorHover = frameColorHover self.frameColorPress = frameColorPress self.textColorReady = textColorReady self.textColorHover = textColorHover self.textColorPress = textColorPress self.textColorDisabled = textColorDisabled self.minZ = minZ self.mpos = Point2(base.mouseWatcherNode.getMouse()) self.itemCommand = [] self.hotkeys = {} self.numItems = 0 self.sel = -1 self.selByKey = False bgPad = self.bgPad = .0125 texMargin = self.font.getTextureMargin() * self.scale[0] * .25 b = DirectButton(parent=NodePath(''), text='^|g_', text_font=self.font, scale=self.scale) fr = b.node().getFrame() b.getParent().removeNode() baselineToCenter = (fr[2] + fr[3]) * self.scale[0] LH = (fr[3] - fr[2]) * self.itemHeight * self.scale[2] imageHalfHeight = .5 * (fr[3] - fr[2]) * self.itemHeight * .85 arrowHalfHeight = .5 * (fr[3] - fr[2]) * self.itemHeight * .5 baselineToTop = (fr[3] * self.itemHeight * self.scale[2] / LH) / (1. + self.baselineOffset) baselineToBot = LH / self.scale[2] - baselineToTop itemZcenter = (baselineToTop - baselineToBot) * .5 separatorHalfHeight = .5 * separatorHeight * LH LSseparator = LineSegs() LSseparator.setColor(.5, .5, .5, .2) arrowVtx = [ (0, itemZcenter), (-2 * arrowHalfHeight, itemZcenter + arrowHalfHeight), (-arrowHalfHeight, itemZcenter), (-2 * arrowHalfHeight, itemZcenter - arrowHalfHeight), ] tri = Triangulator() vdata = GeomVertexData('trig', GeomVertexFormat.getV3(), Geom.UHStatic) vwriter = GeomVertexWriter(vdata, 'vertex') for x, z in arrowVtx: vi = tri.addVertex(x, z) vwriter.addData3f(x, 0, z) tri.addPolygonVertex(vi) tri.triangulate() prim = GeomTriangles(Geom.UHStatic) for i in range(tri.getNumTriangles()): prim.addVertices(tri.getTriangleV0(i), tri.getTriangleV1(i), tri.getTriangleV2(i)) prim.closePrimitive() geom = Geom(vdata) geom.addPrimitive(prim) geomNode = GeomNode('arrow') geomNode.addGeom(geom) realArrow = NodePath(geomNode) z = -baselineToTop * self.scale[2] - bgPad maxWidth = .1 / self.scale[0] shortcutTextMaxWidth = 0 anyImage = False anyArrow = False anyShortcut = False arrows = [] shortcutTexts = [] loadPrcFileData('', 'text-flatten 0') for item in items: if item: t, imgPath, f = item[:3] haveSubmenu = type(f) in SEQUENCE_TYPES anyArrow |= haveSubmenu anyImage |= isinstance(imgPath, bool) or bool(imgPath) disabled = not len(f) if haveSubmenu else not callable(f) args = item[3:] underlinePos = t.find('_') t = t.replace('_', '') shortcutSepPos = t.find('>') if shortcutSepPos > -1: if haveSubmenu: print( "\nA SHORTCUT KEY POINTING TO A SUBMENU IS NON-SENSE, DON'T YOU AGREE ?" ) else: shortcutText = NodePath( OnscreenText( parent=self.menu, text=t[shortcutSepPos + 1:], font=self.font, scale=1, fg=(1, 1, 1, 1), align=TextNode.ARight, )) shortcutTextMaxWidth = max( shortcutTextMaxWidth, abs(shortcutText.getTightBounds()[0][0])) anyShortcut = True t = t[:shortcutSepPos] else: shortcutText = '' EoLcount = t.count('\n') arrowZpos = -self.font.getLineHeight() * EoLcount * .5 if disabled: b = NodePath( OnscreenText( parent=self.menu, text=t, font=self.font, scale=1, fg=textColorDisabled, align=TextNode.ALeft, )) # don't pass the scale and position to OnscreenText constructor, # to maintain correctness between the OnscreenText and DirectButton items # due to the new text generation implementation b.setScale(self.scale) b.setZ(z) maxWidth = max(maxWidth, b.getTightBounds()[1][0] / self.scale[0]) if shortcutText: shortcutText.reparentTo(b) shortcutText.setColor(Vec4(*textColorDisabled), 1) shortcutText.setZ(arrowZpos) shortcutTexts.append(shortcutText) else: b = DirectButton( parent=self.menu, text=t, text_font=self.font, scale=self.scale, pos=(0, 0, z), text_fg=textColorReady, # text color when mouse over text2_fg=textColorHover, # text color when pressed text1_fg=textColorHover if haveSubmenu else textColorPress, # framecolor when pressed frameColor=frameColorHover if haveSubmenu else frameColorPress, commandButtons=[DGG.LMB, DGG.RMB], command=(lambda: 0) if haveSubmenu else self.__runCommand, extraArgs=[] if haveSubmenu else [f, args], text_align=TextNode.ALeft, relief=DGG.FLAT, rolloverSound=0, clickSound=0, pressEffect=0) b.stateNodePath[2].setColor( *frameColorHover) # framecolor when mouse over b.stateNodePath[0].setColor(0, 0, 0, 0) # framecolor when ready bframe = Vec4(b.node().getFrame()) if EoLcount: bframe.setZ(EoLcount * 10) b['frameSize'] = bframe maxWidth = max(maxWidth, bframe[1]) if shortcutText: for snpi, col in ((0, textColorReady), (1, textColorPress), (2, textColorHover)): sct = shortcutText.copyTo(b.stateNodePath[snpi], sort=10) sct.setColor(Vec4(*col), 1) sct.setZ(arrowZpos) shortcutTexts.append(sct) shortcutText.removeNode() if isinstance(imgPath, bool): if imgPath: if disabled: fg = textColorDisabled else: fg = textColorReady tick = NodePath( OnscreenText( parent=b, text=u"\u2714", font=self.font, scale=1, fg=fg, align=TextNode.ALeft, )) tick.setX(-2 * imageHalfHeight - leftPad) elif imgPath: img = loader.loadTexture(imgPath, okMissing=True) if img is not None: if disabled: if imgPath in PopupMenu.grayImages: img = PopupMenu.grayImages[imgPath] else: pnm = PNMImage() img.store(pnm) pnm.makeGrayscale(.2, .2, .2) img = Texture() img.load(pnm) PopupMenu.grayImages[imgPath] = img img.setMinfilter(Texture.FTLinearMipmapLinear) img.setWrapU(Texture.WMClamp) img.setWrapV(Texture.WMClamp) CM = CardMaker('') CM.setFrame(-2 * imageHalfHeight - leftPad, -leftPad, itemZcenter - imageHalfHeight, itemZcenter + imageHalfHeight) imgCard = b.attachNewNode(CM.generate()) imgCard.setTexture(img) if underlinePos > -1: oneLineText = t[:underlinePos + 1] oneLineText = oneLineText[oneLineText.rfind('\n') + 1:] tn = TextNode('') tn.setFont(self.font) tn.setText(oneLineText) tnp = NodePath(tn.getInternalGeom()) underlineXend = tnp.getTightBounds()[1][0] tnp.removeNode() tn.setText(t[underlinePos]) tnp = NodePath(tn.getInternalGeom()) b3 = tnp.getTightBounds() underlineXstart = underlineXend - (b3[1] - b3[0])[0] tnp.removeNode() underlineZpos = -.7 * baselineToBot - self.font.getLineHeight( ) * t[:underlinePos].count('\n') LSunder = LineSegs() LSunder.setThickness(underscoreThickness) LSunder.moveTo(underlineXstart + texMargin, 0, underlineZpos) LSunder.drawTo(underlineXend - texMargin, 0, underlineZpos) if disabled: underline = b.attachNewNode(LSunder.create()) underline.setColor(Vec4(*textColorDisabled), 1) else: underline = b.stateNodePath[0].attachNewNode( LSunder.create()) underline.setColor(Vec4(*textColorReady), 1) underline.copyTo(b.stateNodePath[1], 10).setColor( Vec4(*textColorHover if haveSubmenu else textColorPress), 1) underline.copyTo(b.stateNodePath[2], 10).setColor(Vec4(*textColorHover), 1) hotkey = t[underlinePos].lower() if hotkey in self.hotkeys: self.hotkeys[hotkey].append(self.numItems) else: self.hotkeys[hotkey] = [self.numItems] self.accept(self.BTprefix + hotkey, self.__processHotkey, [hotkey]) self.accept(self.BTprefix + 'alt-' + hotkey, self.__processHotkey, [hotkey]) if haveSubmenu: if disabled: arrow = realArrow.instanceUnderNode(b, '') arrow.setColor(Vec4(*textColorDisabled), 1) arrow.setZ(arrowZpos) else: arrow = realArrow.instanceUnderNode( b.stateNodePath[0], 'r') arrow.setColor(Vec4(*textColorReady), 1) arrow.setZ(arrowZpos) arrPress = realArrow.instanceUnderNode( b.stateNodePath[1], 'p') arrPress.setColor(Vec4(*textColorHover), 1) arrPress.setZ(arrowZpos) arrHover = realArrow.instanceUnderNode( b.stateNodePath[2], 'h') arrHover.setColor(Vec4(*textColorHover), 1) arrHover.setZ(arrowZpos) # weird, if sort order is 0, it's obscured by the frame for a in (arrPress, arrHover): a.reparentTo(a.getParent(), sort=10) if not disabled: extraArgs = [self.numItems, f if haveSubmenu else 0] self.accept(DGG.ENTER + b.guiId, self.__hoverOnItem, extraArgs) self.accept(DGG.EXIT + b.guiId, self.__offItem) #~ self.itemCommand.append((None,0) if haveSubmenu else (f,args)) self.itemCommand.append((f, args)) if self.numItems == 0: self.firstButtonIdx = int(b.guiId[2:]) self.numItems += 1 z -= LH + self.font.getLineHeight() * self.scale[2] * EoLcount else: # SEPARATOR LINE z += LH - separatorHalfHeight - baselineToBot * self.scale[2] LSseparator.moveTo(0, 0, z) LSseparator.drawTo(self.scale[0] * .5, 0, z) LSseparator.drawTo(self.scale[0], 0, z) z -= separatorHalfHeight + baselineToTop * self.scale[2] maxWidth += 7 * arrowHalfHeight * ( anyArrow or anyShortcut) + .2 + shortcutTextMaxWidth arrowXpos = maxWidth - arrowHalfHeight realArrow.setX(arrowXpos) if anyImage: leftPad += 2 * imageHalfHeight + leftPad for sct in shortcutTexts: sct.setX(maxWidth - 2 * (arrowHalfHeight * anyArrow + .2)) for c in asList(self.menu.findAllMatches('**/DirectButton*')): numLines = c.node().getFrame()[2] c.node().setFrame( Vec4( -leftPad, maxWidth, -baselineToBot - (numLines * .1 * self.itemHeight if numLines >= 10 else 0), baselineToTop)) loadPrcFileData('', 'text-flatten 1') try: minZ = self.menu.getChild(0).getRelativePoint( b, Point3(0, 0, b.node().getFrame()[2]))[2] except: minZ = self.menu.getChild(0).getRelativePoint( self.menu, Point3( 0, 0, b.getTightBounds()[0][2]))[2] - baselineToBot * .5 try: top = self.menu.getChild(0).node().getFrame()[3] except: top = self.menu.getChild(0).getZ() + baselineToTop l, r, b, t = -leftPad - bgPad / self.scale[ 0], maxWidth + bgPad / self.scale[0], minZ - bgPad / self.scale[ 2], top + bgPad / self.scale[2] menuBG = DirectFrame(parent=self.menu.getChild(0), frameSize=(l, r, b, t), frameColor=BGColor, state=DGG.NORMAL, suppressMouse=1) menuBorder = self.menu.getChild(0).attachNewNode('border') borderVtx = ( (l, 0, b), (l, 0, .5 * (b + t)), (l, 0, t), (.5 * (l + r), 0, t), (r, 0, t), (r, 0, .5 * (b + t)), (r, 0, b), (.5 * (l + r), 0, b), (l, 0, b), ) LSborderBG = LineSegs() LSborderBG.setThickness(4) LSborderBG.setColor(0, 0, 0, .7) LSborderBG.moveTo(*(borderVtx[0])) for v in borderVtx[1:]: LSborderBG.drawTo(*v) # fills the gap at corners for v in range(0, 7, 2): LSborderBG.moveTo(*(borderVtx[v])) menuBorder.attachNewNode(LSborderBG.create()) LSborder = LineSegs() LSborder.setThickness(2) LSborder.setColor(*BGBorderColor) LSborder.moveTo(*(borderVtx[0])) for v in borderVtx[1:]: LSborder.drawTo(*v) menuBorder.attachNewNode(LSborder.create()) for v in range(1, 8, 2): LSborderBG.setVertexColor(v, Vec4(0, 0, 0, .1)) LSborder.setVertexColor(v, Vec4(.3, .3, .3, .5)) menuBorderB3 = menuBorder.getTightBounds() menuBorderDims = menuBorderB3[1] - menuBorderB3[0] menuBG.wrtReparentTo(self.menu, sort=-1) self.menu.reparentTo(self.parent) x = -menuBorderB3[0][0] * self.scale[0] for c in asList(self.menu.getChildren()): c.setX(x) self.maxWidth = maxWidth = menuBorderDims[0] self.height = menuBorderDims[2] maxWidthR2D = maxWidth * self.menu.getChild(0).getSx(render2d) separatorLines = self.menu.attachNewNode(LSseparator.create(), 10) separatorLines.setSx(maxWidth) for v in range(1, LSseparator.getNumVertices(), 3): LSseparator.setVertexColor(v, Vec4(*separatorColor)) x = clamp(-.98, .98 - maxWidthR2D, self.mpos[0] - maxWidthR2D * .5) minZ = (-.98 if self.minZ is None else self.minZ) z = clamp( minZ + menuBorderDims[2] * self.scale[2] * self.parent.getSz(render2d), .98, self.mpos[1] if useMouseZ else -1000) self.menu.setPos(render2d, x, 0, z) self.menu.setTransparency(1) self.origBTprefix = self.BT.getPrefix() self.BT.setPrefix(self.BTprefix) self.accept(self.BTprefix + 'escape', self.destroy) for e in ('mouse1', 'mouse3'): self.accept(self.BTprefix + e, self.destroy, [True]) self.accept(self.BTprefix + 'arrow_down', self.__nextItem) self.accept(self.BTprefix + 'arrow_down-repeat', self.__nextItem) self.accept(self.BTprefix + 'arrow_up', self.__prevItem) self.accept(self.BTprefix + 'arrow_up-repeat', self.__prevItem) self.accept(self.BTprefix + 'enter', self.__runSelItemCommand) self.accept(self.BTprefix + 'space', self.__runSelItemCommand) def __offItem(self, crap): self.sel = -1 self.__cancelSubmenuCreation() def __hoverOnItem(self, idx, menu, crap): self.sel = idx self.__cancelSubmenuCreation() if self.BT.getPrefix()==self.BTprefix or \ (self.submenu and self.submenuIdx==idx): self.__cancelSubmenuRemoval() if menu: if not (self.submenu and self.submenuIdx == idx): #~ if self.selByKey: #~ self.selByKey=False #~ self.__createSubmenu(idx,menu) #~ else: taskMgr.doMethodLater(.3, self.__createSubmenu, self.submenuCreationTaskName, extraArgs=[idx, menu]) else: taskMgr.doMethodLater(.5, self.__removeSubmenu, self.submenuRemovalTaskName, extraArgs=[]) def __cancelSubmenuCreation(self): taskMgr.removeTasksMatching('createSubMenu-*') def __createSubmenu(self, idx, menu): self.__cancelSubmenuCreation() self.__removeSubmenu() self.submenu = PopupMenu(items=menu, parent=self.parent, buttonThrower=self.BT, font=self.font, baselineOffset=self.baselineOffset, scale=self.scale, itemHeight=self.itemHeight, leftPad=self.leftPad, separatorHeight=self.separatorHeight, underscoreThickness=self.underscoreThickness, BGColor=self.BGColor, BGBorderColor=self.BGBorderColor, separatorColor=self.separatorColor, frameColorHover=self.frameColorHover, frameColorPress=self.frameColorPress, textColorReady=self.textColorReady, textColorHover=self.textColorHover, textColorPress=self.textColorPress, textColorDisabled=self.textColorDisabled, minZ=self.minZ, useMouseZ=False) self.submenuIdx = idx self.submenu.parentMenu = self if self.menu.getBinName(): self.submenu.menu.setBin(self.menu.getBinName(), self.menu.getBinDrawOrder() + 1) sb3 = self.submenu.menu.getTightBounds() sb = sb3[1] - sb3[0] b3 = self.menu.getTightBounds() x = b3[1][0] if render2d.getRelativePoint(self.parent, Point3(x + sb[0], 0, 0))[0] > .98: x = b3[0][0] - sb[0] if render2d.getRelativePoint(self.parent, Point3(x, 0, 0))[0] < -.98: x = self.parent.getRelativePoint(render2d, Point3(-.98, 0, 0))[0] item = self.menu.find('**/*-pg%s' % (self.firstButtonIdx + idx)) z = self.parent.getRelativePoint( item, Point3(0, 0, item.node().getFrame()[3]))[2] + self.bgPad self.submenu.menu.setPos(x, 0, max(z, self.submenu.menu.getZ())) # self.submenu.menu.setPos(x,0,z) def __nextItem(self): if self.numItems: self.sel = clamp(0, self.numItems - 1, self.sel + 1) self.__putPointerAtItem() self.selByKey = True def __prevItem(self): if self.numItems: self.sel = clamp(0, self.numItems - 1, (self.sel - 1) if self.sel > -1 else self.numItems - 1) self.__putPointerAtItem() self.selByKey = True def __putPointerAtItem(self): item = self.menu.find('**/*-pg%s' % (self.firstButtonIdx + self.sel)) fr = item.node().getFrame() c = Point3(.5 * (fr[0] + fr[1]), 0, .5 * (fr[2] + fr[3])) cR2D = render2d.getRelativePoint(item, c) x, y = int(base.win.getXSize() * .5 * (cR2D[0] + 1)), int( base.win.getYSize() * .5 * (-cR2D[2] + 1)) if '__origmovePointer' in base.win.DtoolClassDict: base.win.DtoolClassDict['__origmovePointer'](base.win, 0, x, y) else: base.win.movePointer(0, x, y) def __processHotkey(self, hotkey): itemsIdx = self.hotkeys[hotkey] if len(itemsIdx) == 1 and type( self.itemCommand[itemsIdx[0]][0]) not in SEQUENCE_TYPES: self.__runCommand(*self.itemCommand[itemsIdx[0]]) else: if self.sel in itemsIdx: idx = itemsIdx.index(self.sel) + 1 idx %= len(itemsIdx) self.sel = itemsIdx[idx] else: self.sel = itemsIdx[0] self.selByKey = True # if it's already there, putting the pointer doesn't trigger the 'enter' # event, so just bypass it if not (self.submenu and self.submenuIdx==self.sel) and\ type(self.itemCommand[itemsIdx[0]][0]) in SEQUENCE_TYPES: self.__createSubmenu(self.sel, self.itemCommand[itemsIdx[0]][0]) self.__putPointerAtItem() def __doRunCommand(self, f, args): self.destroy(delParents=True) f(*args) def __runCommand(self, f, args): if callable(f): # must be done at next frame, so shortcut key event won't bleed to the scene taskMgr.doMethodLater(.01, self.__doRunCommand, 'run menu command', extraArgs=[f, args]) def __runSelItemCommand(self): if self.sel == -1: return self.__runCommand(*self.itemCommand[self.sel]) def __cancelSubmenuRemoval(self): taskMgr.removeTasksMatching('removeSubMenu-*') def __removeSubmenu(self): self.__cancelSubmenuRemoval() if self.submenu: self.submenu.destroy() def destroy(self, delParents=False): self.__cancelSubmenuCreation() self.__removeSubmenu() self.subMenu = None self.ignoreAll() self.menu.removeNode() # if self.origBTprefix.find('menu-')==-1: # taskMgr.step() self.BT.setPrefix(self.origBTprefix) messenger.send(self.BTprefix + 'destroyed') if delParents and self.parentMenu: parent = self.parentMenu while parent.parentMenu: parent = parent.parentMenu parent.destroy() if self.parentMenu: self.parentMenu.submenuIdx = None self.parentMenu = None if callable(self.onDestroy): self.onDestroy()