def precacheScene(scene, reset=True): if reset: oldp = scene.getParent() rHidden = False if render.isHidden(): rHidden = True render.show() stashed = NodePathCollection() for np in scene.findAllMatches("**;+s"): if np.isStashed(): stashed.addPath(np) np.unstash() if not scene.isAncestorOf(render): # if it's parented to camera, # camera will always see it scene.reparentTo(render) # this says that the scene takes up infinite space, # making it always intersect the view frustum, # guaranteed to be rendered scene.node().setBounds(OmniBoundingVolume()) scene.node().setFinal(1) # Always render if it's a BSP level, even if outside of PVS scene.setAttrib(BSPFaceAttrib.makeIgnorePvs(), 1) try: scene.premungeScene(base.win.getGsg()) scene.prepareScene(base.win.getGsg()) base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() base.graphicsEngine.syncFrame() base.musicManager.update() if reset: scene.node().setFinal(0) scene.node().clearBounds() scene.reparentTo(oldp) if rHidden: render.hide() # restash for np in stashed: np.stash() except: # The program might have exited prematurely. # This will prevent the game from yelling at us. print("precacheScene failed") scene.clearAttrib(BSPFaceAttrib) return rHidden
def optimizePhys(root): colls = 0 npc = NodePathCollection() for child in root.getChildren(): if child.node().isOfType(CollisionNode.getClassType()): colls += 1 npc.addPath(child) if colls > 1: collide = root.attachNewNode("__collide__") npc.wrtReparentTo(collide) collide.clearModelNodes() collide.flattenStrong() # Move the possibly combined collisionNodes back to the root. collide.getChildren().wrtReparentTo(root) collide.removeNode() for child in root.getChildren(): if child.getName() != '__collide__': optimizePhys(child)
def TraverserLevelFirst(startNP, funcOpOnNP, *args, **kwargs): npCollection = NodePathCollection() currNP = startNP npCollection.addPath(currNP) notEmtpy = True while notEmtpy: if currNP.countNumDescendants() == 0: # no descendants to add to the stack pass else: # add the currNP's children to stack currChildColl = currNP.getChildren() npCollection.extend(currChildColl) if npCollection.getNumPaths() > 0: # operate on the current node funcOpOnNP(currNP, *args, **kwargs) npCollection.removePath(currNP) # get currNP's sister if npCollection.getNumPaths() > 0: currNP = npCollection.getPath(0) else: notEmtpy = False # scene has been walked in level order currNP = None
def remove(self, psos): """ Remove sequence of PSOs from compound object.""" with self._preserve_child_tranforms(): NodePathCollection(psos).detach() if self.getNumChildren() > 0: self._compute_shapes()
def add(self, psos): """ Add sequence of PSOs to compound object.""" NodePathCollection(psos).wrtReparentTo(self) self._compute_shapes()
def __init__(self, parent): DirectObject.DirectObject.__init__(self) self.debugMode = config.GetInt('loading-screen') == 2 self.parent = parent self.state = False self.currScreenshot = None self.snapshot = None self.snapshotFrame = None self.snapshotFrameBasic = None self.currentTime = 0 self.analyzeMode = False self.loadScale = 1.0 self.unmappedTicks = [] self.stepInfo = { } self.accept(base.win.getWindowEvent(), self.adjustSize) self.accept('tick', self.tick) self.currStage = 'unmapped' self.stagePercent = 0 self.numObjects = 0 self.currPercent = 0.0 self.line = LineSegs() self.line.setColor((0, 0, 0, 1)) self.line.setThickness(1) self.stageLabel = None self.currNum = 0 self.overallPercent = 0 self.lastPercent = 0 self.topLock = aspect2dp.attachNewNode('topShift') self.root = self.topLock.attachNewNode('loadingScreenRoot') self.root.setZ(-1) self.root.stash() self.model = loader.loadModel('models/gui/pir_m_gui_gen_loadScreen.bam') self.model.setP(90) self.model.reparentTo(self.root) cm = CardMaker('backdrop') cm.setFrame(-10, 10, -10, 10) if self.debugMode: self.backdrop = self.root.attachNewNode(cm.generate()) self.backdrop.setX(-1.5) self.backdrop.setZ(-1) self.backdrop.setScale(4) self.backdrop.setColor(0.5, 0.5, 0.5, 1) cm = CardMaker('loadingBarBase') cm.setFrame(-0.90000000000000002, 0.90000000000000002, 0.10000000000000001, 0.5) self.loadingBarBacking = self.root.attachNewNode(cm.generate()) self.loadingBarRoot = self.root.attachNewNode('loadingBarRoot') cm.setName('analysisBarBase') cm.setFrame(-0.90000000000000002, 0.90000000000000002, -0.5, -0.10000000000000001) self.analysisBar = self.root.attachNewNode(cm.generate()) self.analysisBarRoot = self.root.attachNewNode('analysisBarRoot') self.analysisBar.hide() self.analysisButtons = [] self.enterToContinue = DirectLabel(parent = self.root, text = 'Press Shift To Continue', relief = None, text_scale = 0.10000000000000001, pos = (0, 0, -0.90000000000000002), text_align = TextNode.ACenter) self.enterToContinue.hide() self.stageLabel = DirectLabel(parent = self.root, text = '', relief = None, text_scale = 0.10000000000000001, pos = (-1.25, 0, 0.75), text_align = TextNode.ALeft, textMayChange = 1) self.tickLabel = DirectLabel(parent = self.root, text = '', relief = None, text_scale = 0.10000000000000001, pos = (0.75, 0, 0.75), textMayChange = 1) self.overallLabel = DirectLabel(parent = self.root, text = '', relief = None, text_scale = 0.10000000000000001, pos = (0, 0, -0.75), textMayChange = 1) else: self.backdrop = loader.loadModel('models/gui/pir_m_gui_gen_loadScreen') self.backdrop.reparentTo(self.root) bg = self.backdrop.find('**/expandable_bg') bg.setScale(1000, 1, 1000) bg.flattenStrong() self.backdrop.find('**/loadbar_grey').setColorScale(0.14999999999999999, 0.14999999999999999, 0.14999999999999999, 0.10000000000000001) self.loadingBar = self.backdrop.find('**/loadbar') self.loadingBar.setColorScale(0.20000000000000001, 0.59999999999999998, 0.5, 1) self.loadingPlank = NodePathCollection() self.loadingPlank.addPath(self.backdrop.find('**/plank_loading_bar')) self.loadingPlank.addPath(self.backdrop.find('**/loadbar')) self.loadingPlank.addPath(self.backdrop.find('**/loadbar_frame')) self.loadingPlank.addPath(self.backdrop.find('**/loadbar_grey')) self.titlePlank = self.backdrop.find('**/plank_title') self.percentLabel = DirectLabel(text = '0%', parent = self.root, relief = None, text_font = PiratesGlobals.getPirateFont(), text_fg = PiratesGuiGlobals.TextFG2, text_shadow = PiratesGuiGlobals.TextShadow, text_scale = 0.031, pos = (0, 0, -0.44450000000000001), textMayChange = 1) self.loadingPlank.addPath(self.percentLabel) self.screenshot = self.backdrop.find('**/screenshot') copyGeom = self.loadingBar.find('**/+GeomNode').node().getGeom(0) format = copyGeom.getVertexData().getFormat() primitive = copyGeom.getPrimitive(0) data = GeomVertexData(self.screenshot.node().getGeom(0).getVertexData()) data.setFormat(format) writer = GeomVertexWriter(data, 'texcoord') writer.setData2f(0, 0) writer.setData2f(1, 0) writer.setData2f(1, 1) writer.setData2f(0, 1) geom = Geom(data) geom.addPrimitive(primitive) self.screenshot.node().removeGeom(0) self.screenshot.node().addGeom(geom) self.titlePlankMiddle = self.backdrop.find('**/plank_title_middle_box') self.titlePlankLeft = self.backdrop.find('**/plank_title_left') self.titlePlankRight = self.backdrop.find('**/plank_title_right') self.loadingBarColors = [ (((i % 10) / 10.0 + 0.5) / 2.0, ((i % 100) / 10 / 10.0 + 0.5) / 2.0, (i / 100 / 10.0 + 0.5) / 2.0, 1) for i in range(1000) ] random.shuffle(self.loadingBarColors) self.lastUpdateTime = globalClock.getRealTime() self.locationLabel = DirectLabel(parent = self.root, relief = None, text = '', text_font = PiratesGlobals.getPirateOutlineFont(), text_fg = PiratesGuiGlobals.TextFG1, text_shadow = PiratesGuiGlobals.TextShadow, text_scale = PiratesGuiGlobals.TextScaleTitleJumbo * 0.69999999999999996, text_align = TextNode.ACenter, pos = (0.0, 0.0, 0.51500000000000001), textMayChange = 1) self.locationText = None self.hintLabel = DirectLabel(parent = self.root, relief = None, text = '', text_font = PiratesGlobals.getPirateOutlineFont(), text_fg = PiratesGuiGlobals.TextFG1, text_shadow = PiratesGuiGlobals.TextShadow, text_scale = PiratesGuiGlobals.TextScaleTitleJumbo * 0.5, text_align = TextNode.ACenter, pos = (0.0, 0.0, -0.62), text_wordwrap = 30, textMayChange = 1) self.hintText = None self.adImage = None self.allowLiveFlatten = ConfigVariableBool('allow-live-flatten') self.title_art = [] self.tempVolume = [] self.adjustSize(base.win) gsg = base.win.getGsg() if gsg: self.root.prepareScene(gsg)
class FancyLoadingScreen(DirectObject.DirectObject): notify = DirectNotifyGlobal.directNotify.newCategory('LoadingScreen') def __init__(self, parent): DirectObject.DirectObject.__init__(self) self.debugMode = config.GetInt('loading-screen') == 2 self.parent = parent self.state = False self.currScreenshot = None self.snapshot = None self.snapshotFrame = None self.snapshotFrameBasic = None self.currentTime = 0 self.analyzeMode = False self.loadScale = 1.0 self.unmappedTicks = [] self.stepInfo = { } self.accept(base.win.getWindowEvent(), self.adjustSize) self.accept('tick', self.tick) self.currStage = 'unmapped' self.stagePercent = 0 self.numObjects = 0 self.currPercent = 0.0 self.line = LineSegs() self.line.setColor((0, 0, 0, 1)) self.line.setThickness(1) self.stageLabel = None self.currNum = 0 self.overallPercent = 0 self.lastPercent = 0 self.topLock = aspect2dp.attachNewNode('topShift') self.root = self.topLock.attachNewNode('loadingScreenRoot') self.root.setZ(-1) self.root.stash() self.model = loader.loadModel('models/gui/pir_m_gui_gen_loadScreen.bam') self.model.setP(90) self.model.reparentTo(self.root) cm = CardMaker('backdrop') cm.setFrame(-10, 10, -10, 10) if self.debugMode: self.backdrop = self.root.attachNewNode(cm.generate()) self.backdrop.setX(-1.5) self.backdrop.setZ(-1) self.backdrop.setScale(4) self.backdrop.setColor(0.5, 0.5, 0.5, 1) cm = CardMaker('loadingBarBase') cm.setFrame(-0.90000000000000002, 0.90000000000000002, 0.10000000000000001, 0.5) self.loadingBarBacking = self.root.attachNewNode(cm.generate()) self.loadingBarRoot = self.root.attachNewNode('loadingBarRoot') cm.setName('analysisBarBase') cm.setFrame(-0.90000000000000002, 0.90000000000000002, -0.5, -0.10000000000000001) self.analysisBar = self.root.attachNewNode(cm.generate()) self.analysisBarRoot = self.root.attachNewNode('analysisBarRoot') self.analysisBar.hide() self.analysisButtons = [] self.enterToContinue = DirectLabel(parent = self.root, text = 'Press Shift To Continue', relief = None, text_scale = 0.10000000000000001, pos = (0, 0, -0.90000000000000002), text_align = TextNode.ACenter) self.enterToContinue.hide() self.stageLabel = DirectLabel(parent = self.root, text = '', relief = None, text_scale = 0.10000000000000001, pos = (-1.25, 0, 0.75), text_align = TextNode.ALeft, textMayChange = 1) self.tickLabel = DirectLabel(parent = self.root, text = '', relief = None, text_scale = 0.10000000000000001, pos = (0.75, 0, 0.75), textMayChange = 1) self.overallLabel = DirectLabel(parent = self.root, text = '', relief = None, text_scale = 0.10000000000000001, pos = (0, 0, -0.75), textMayChange = 1) else: self.backdrop = loader.loadModel('models/gui/pir_m_gui_gen_loadScreen') self.backdrop.reparentTo(self.root) bg = self.backdrop.find('**/expandable_bg') bg.setScale(1000, 1, 1000) bg.flattenStrong() self.backdrop.find('**/loadbar_grey').setColorScale(0.14999999999999999, 0.14999999999999999, 0.14999999999999999, 0.10000000000000001) self.loadingBar = self.backdrop.find('**/loadbar') self.loadingBar.setColorScale(0.20000000000000001, 0.59999999999999998, 0.5, 1) self.loadingPlank = NodePathCollection() self.loadingPlank.addPath(self.backdrop.find('**/plank_loading_bar')) self.loadingPlank.addPath(self.backdrop.find('**/loadbar')) self.loadingPlank.addPath(self.backdrop.find('**/loadbar_frame')) self.loadingPlank.addPath(self.backdrop.find('**/loadbar_grey')) self.titlePlank = self.backdrop.find('**/plank_title') self.percentLabel = DirectLabel(text = '0%', parent = self.root, relief = None, text_font = PiratesGlobals.getPirateFont(), text_fg = PiratesGuiGlobals.TextFG2, text_shadow = PiratesGuiGlobals.TextShadow, text_scale = 0.031, pos = (0, 0, -0.44450000000000001), textMayChange = 1) self.loadingPlank.addPath(self.percentLabel) self.screenshot = self.backdrop.find('**/screenshot') copyGeom = self.loadingBar.find('**/+GeomNode').node().getGeom(0) format = copyGeom.getVertexData().getFormat() primitive = copyGeom.getPrimitive(0) data = GeomVertexData(self.screenshot.node().getGeom(0).getVertexData()) data.setFormat(format) writer = GeomVertexWriter(data, 'texcoord') writer.setData2f(0, 0) writer.setData2f(1, 0) writer.setData2f(1, 1) writer.setData2f(0, 1) geom = Geom(data) geom.addPrimitive(primitive) self.screenshot.node().removeGeom(0) self.screenshot.node().addGeom(geom) self.titlePlankMiddle = self.backdrop.find('**/plank_title_middle_box') self.titlePlankLeft = self.backdrop.find('**/plank_title_left') self.titlePlankRight = self.backdrop.find('**/plank_title_right') self.loadingBarColors = [ (((i % 10) / 10.0 + 0.5) / 2.0, ((i % 100) / 10 / 10.0 + 0.5) / 2.0, (i / 100 / 10.0 + 0.5) / 2.0, 1) for i in range(1000) ] random.shuffle(self.loadingBarColors) self.lastUpdateTime = globalClock.getRealTime() self.locationLabel = DirectLabel(parent = self.root, relief = None, text = '', text_font = PiratesGlobals.getPirateOutlineFont(), text_fg = PiratesGuiGlobals.TextFG1, text_shadow = PiratesGuiGlobals.TextShadow, text_scale = PiratesGuiGlobals.TextScaleTitleJumbo * 0.69999999999999996, text_align = TextNode.ACenter, pos = (0.0, 0.0, 0.51500000000000001), textMayChange = 1) self.locationText = None self.hintLabel = DirectLabel(parent = self.root, relief = None, text = '', text_font = PiratesGlobals.getPirateOutlineFont(), text_fg = PiratesGuiGlobals.TextFG1, text_shadow = PiratesGuiGlobals.TextShadow, text_scale = PiratesGuiGlobals.TextScaleTitleJumbo * 0.5, text_align = TextNode.ACenter, pos = (0.0, 0.0, -0.62), text_wordwrap = 30, textMayChange = 1) self.hintText = None self.adImage = None self.allowLiveFlatten = ConfigVariableBool('allow-live-flatten') self.title_art = [] self.tempVolume = [] self.adjustSize(base.win) gsg = base.win.getGsg() if gsg: self.root.prepareScene(gsg) def startLoading(self, expectedLoadScale): if not self.debugMode: self.loadingBar.setSx(0) self.loadScale = float(expectedLoadScale) self.currStage = 'unmapped' self.stagePercent = 0 self.numObjects = 0 self.currPercent = 0.0 self.loadingStart = globalClock.getRealTime() self.currNum = 0 self.overallPercent = 0 self.lastPercent = 0 self.stepNum = 0 if self.debugMode: self.overallLabel['text'] = '0.0' self.stageLabel['text'] = self.currStage self.update() def beginStep(self, stageName, amt = 0, percent = 0.001): if not self.state: return None if self.currStage != 'unmapped' and stageName != self.currStage: if __dev__ and self.debugMode: self.notify.error('step %s not finished when step %s was started!' % (self.currStage, stageName)) else: self.notify.warning('step %s not finished when step %s was started!' % (self.currStage, stageName)) return None self.stepNum += 1 if self.debugMode: stageColor = self.loadingBarColors[self.stepNum] self.stepInfo[stageName] = [ globalClock.getRealTime() - self.loadingStart, 0.0, stageColor, [], self.lastPercent + self.stagePercent, percent, amt] self.stepCard = CardMaker('step-%s' % stageName) self.stepCard.setColor(stageColor) self.currPoly = NodePath('empty') self.stageLabel['text'] = stageName self.tickLabel['text'] = '0.0' self.currPercent = 0.0 self.overallPercent = min(100.0 * self.loadScale, self.lastPercent + self.stagePercent) self.lastPercent = self.overallPercent self.currStage = stageName self.stagePercent = percent self.numObjects = amt self.currNum = 0 base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() def endStep(self, stageName): if self.currStage == 'unmapped': self.notify.warning('step %s was started before loading screen was enabled' % stageName) return None if stageName != self.currStage: if __dev__ and self.debugMode: self.notify.error('step %s was active while step %s was trying to end!' % (self.currStage, stageName)) else: return None self.tick() if self.debugMode: stageInfo = self.stepInfo[self.currStage] stageInfo[1] = globalClock.getRealTime() - self.loadingStart - stageInfo[0] self.currPoly.detachNode() self.stepCard.setFrame((self.lastPercent / self.loadScale) * 0.017999999999999999 - 0.90000000000000002, ((self.lastPercent + self.stagePercent) / self.loadScale) * 0.017999999999999999 - 0.90000000000000002, 0.10000000000000001, 0.5) self.loadingBarRoot.attachNewNode(self.stepCard.generate()) self.stageLabel['text'] = 'unmapped' self.currStage = 'unmapped' self.currPercent = 0.0 def tick(self): if self.state == False or self.analyzeMode: return None if self.debugMode: if self.currStage == 'unmapped': self.unmappedTicks.append(globalClock.getRealTime() - self.loadingStart) else: self.stepInfo[self.currStage][3].append(globalClock.getRealTime() - self.loadingStart) self.currNum += 1 self.currPercent = min(1.0, self.currNum / float(self.numObjects + 1)) self.overallPercent = min(100.0 * self.loadScale, self.lastPercent + self.currPercent * self.stagePercent) self.update() def destroy(self): taskMgr.remove('updateLoadingScreen') for part in (self.model, self.snapshot): if part is not None: tex = part.findTexture('*') if tex: tex.releaseAll() part.removeNode() self.model = None self.snapshot = None if self.snapshotFrame: self.snapshotFrame.destroy() if self.snapshotFrameBasic: self.snapshotFrameBasic.destroy() if self.locationLabel: self.locationLabel.destroy() if self.hintLabel: self.hintLabel.destroy() if self.debugMode: self.stageLabel.destroy() self.tickLabel.destroy() self.overallLabel.destroy() self.enterToContinue.destroy() self.stageLabel = None self.tickLabel = None self.overallLabel = None self.enterToContinue = None self.ignoreAll() def showTitleFrame(self): if base.config.GetBool('no-loading-screen', 0): return None for part in self.title_art: part.show() def hideTitleFrame(self): for part in self.title_art: part.hide() def show(self, waitForLocation = False, disableSfx = True, expectedLoadScale = 1.0): if self.state and base.config.GetBool('no-loading-screen', 0) or not (self.locationLabel): return None render.hide() render2d.hide() render2dp.hide() if not self.debugMode: self.loadingPlank.hide() self.root.unstash() self.root.showThrough() self.state = True gsg = base.win.getGsg() if gsg: gsg.setIncompleteRender(False) base.setTaskChainNetNonthreaded() self.allowLiveFlatten.setValue(1) self.startLoading(expectedLoadScale) base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() base.refreshAds() taskMgr.add(self.update, 'updateLoadingScreen', priority = -100) if base.sfxManagerList and disableSfx: index = 0 while index < len(base.sfxManagerList): sfx_manager = base.sfxManagerList[index] sfx_manager.setVolume(0.0) index += 1 if base.appRunner: base.appRunner.notifyRequest('onLoadingMessagesStart') self._FancyLoadingScreen__setLocationText(self.locationText) self._FancyLoadingScreen__setHintText(self.hintText) if not waitForLocation: screenshot = random.choice(tutorialShots_MoveAim) self._FancyLoadingScreen__setLoadingArt(screenshot) def showHint(self, destId = None, ocean = False): if base.config.GetBool('no-loading-screen', 0) or not (self.locationLabel): return None if ocean: hint = getOceanHint() elif hasattr(base, 'localAvatar'): totalReputation = 0 level = base.localAvatar.getLevel() if totalReputation: hint = getHint(destId, level) else: hint = getHint(destId) else: hint = getHint() shipPVPIslands = [ '1196970035.53sdnaik', '1196970080.56sdnaik'] if (destId in shipPVPIslands or ocean) and base.localAvatar.getCurrentIsland() in shipPVPIslands: hint = getPrivateeringHint() if self.parent and base.localAvatar.style.getTutorial() == PiratesGlobals.TUT_MET_JOLLY_ROGER: hint = '%s: %s' % (PLocalizer.LoadingScreen_Hint, PLocalizer.GeneralTip7) self._FancyLoadingScreen__setHintText(hint) def update(self, task = None): if not (self.state) or self.analyzeMode: return Task.cont realTime = globalClock.getRealTime() if realTime - self.lastUpdateTime < 0.10000000000000001: return Task.cont self.currentTime += min(10, (realTime - self.lastUpdateTime) * 250) self.lastUpdateTime = realTime if self.debugMode: self.overallLabel['text'] = '%3.1f' % (self.overallPercent / self.loadScale) self.tickLabel['text'] = '%3.1f' % (self.currPercent * 100.0) else: self.percentLabel['text'] = '%d%%' % (self.overallPercent / self.loadScale) if self.currStage != 'unmapped': if self.debugMode: self.currPoly.detachNode() self.stepCard.setFrame((self.lastPercent / self.loadScale) * 0.017999999999999999 - 0.90000000000000002, (self.overallPercent / self.loadScale) * 0.017999999999999999 - 0.90000000000000002, 0.20000000000000001, 0.40000000000000002) self.currPoly = self.loadingBarRoot.attachNewNode(self.stepCard.generate()) if not self.debugMode: self.loadingBar.setSx((self.overallPercent / self.loadScale) * 3.3999999999999999) if self.overallPercent > 0: self.loadingPlank.show() base.eventMgr.doEvents() base.graphicsEngine.renderFrame() return Task.cont def hide(self, reallyHide = not (config.GetInt('loading-screen', 0) == 2)): if not self.state: return None if not reallyHide: if not self.analyzeMode: self.loadingEnd = globalClock.getRealTime() self.accept('shift', self.hide, extraArgs = [ 1]) self.enterToContinue.show() self.generateAnalysis() return None self.cleanupLoadingScreen() if self.debugMode: self.enterToContinue.hide() self.ignore('shift') self.root.hide() self.root.stash() render2d.show() render2dp.show() render.show() base.graphicsEngine.renderFrame() self.state = False self.currentTime = 0 self.locationText = None self.hintText = None self.currScreenshot = None gsg = base.win.getGsg() if gsg: gsg.setIncompleteRender(True) render.prepareScene(gsg) render2d.prepareScene(gsg) taskMgr.remove('updateLoadingScreen') self.allowLiveFlatten.clearValue() base.setTaskChainNetThreaded() if base.sfxManagerList: index = 0 while index < len(base.sfxManagerList): sfx_manager = base.sfxManagerList[index] sfx_manager.setVolume(base.options.sound_volume) index += 1 messenger.send('texture_state_changed') if base.appRunner: base.appRunner.notifyRequest('onLoadingMessagesStop') def showTarget(self, targetId = None, ocean = False, jail = False, pickapirate = False, exit = False, potionCrafting = False, benchRepair = False, shipRepair = False, cannonDefense = False, fishing = False): if base.config.GetBool('no-loading-screen', 0): return None if pickapirate: screenshot = screenShot_EnterGame elif exit: screenshot = screenShot_ExitGame elif ocean: screenshot = screenShot_Dinghy elif jail: screenshot = screenShot_Jail elif potionCrafting: screenshot = screenShot_Potions elif benchRepair: screenshot = screenShot_BenchRepair elif shipRepair: screenshot = screenShot_ShipRepair elif cannonDefense: screenshot = screenShot_CannonDefense elif fishing: screenshot = screenShot_Fishing elif base.localAvatar.style.getTutorial() < PiratesGlobals.TUT_GOT_CUTLASS: screenshot = screenShot_Weapon elif base.localAvatar.style.getTutorial() < PiratesGlobals.TUT_MET_JOLLY_ROGER: screenshot = screenShot_Cutlass elif base.cr.newsManager and base.cr.newsManager.getHoliday(21): screenshot = screenShots_WinterHolidayLocations.get(targetId) if not screenshot: screenshot = screenShots_Locations.get(targetId) else: screenshot = screenShots_Locations.get(targetId) if not screenshot: if areaType_Jungles.has_key(targetId): screenshot = random.choice(screenShots_Jungles) elif areaType_Swamps.has_key(targetId): screenshot = random.choice(screenShots_Swamps) elif areaType_Caves.has_key(targetId): screenshot = random.choice(screenShots_Caves) else: island = getParentIsland(targetId) screenshot = screenShots_Locations.get(island, [ random.choice(screenShots)])[0] if isinstance(screenshot, list): screenshot = random.choice(screenshot) self._FancyLoadingScreen__setLoadingArt(screenshot) if pickapirate: targetName = PLocalizer.LoadingScreen_PickAPirate elif exit: targetName = None elif ocean: targetName = PLocalizer.LoadingScreen_Ocean elif jail: targetName = PLocalizer.LoadingScreen_Jail else: targetName = PLocalizer.LocationNames.get(targetId) base.setLocationCode('Loading: %s' % targetName) if targetName is None: return None if len(targetName): self._FancyLoadingScreen__setLocationText(targetName) def _FancyLoadingScreen__setLoadingArt(self, screenshot): if self.currScreenshot: return None if self.parent and hasattr(base, 'localAvatar') and base.localAvatar.style.getTutorial() < PiratesGlobals.TUT_MET_JOLLY_ROGER and screenshot not in tutorialShots: screenshot = random.choice(tutorialShots) try: self.currScreenshot = loader.loadModel(screenshot).findAllTextures()[0] except: self.currScreenshot = loader.loadModel(random.choice(screenshot)).findAllTextures()[0] if not self.debugMode: self.screenshot.setTexture(self.currScreenshot) def _FancyLoadingScreen__setLocationText(self, locationText): if self.debugMode: return None self.locationText = locationText if not self.locationText: self.locationText = '' self.titlePlank.hide() if len(self.locationText) > 12: scaleFactor = len(self.locationText) / 12.0 self.titlePlankMiddle.setSx(scaleFactor) self.titlePlankRight.setX(0.215 * scaleFactor - 0.215) self.titlePlankLeft.setX(-1 * (0.215 * scaleFactor - 0.215)) else: self.titlePlankMiddle.setSx(1) self.titlePlankRight.setX(0) self.titlePlankLeft.setX(0) self.locationLabel['text'] = self.locationText if self._FancyLoadingScreen__isVisible() and len(self.locationText): self.locationLabel.show() self.titlePlank.show() else: self.locationLabel.hide() self.titlePlank.hide() launcher.setValue('gameLocation', self.locationText) def _FancyLoadingScreen__setHintText(self, hintText): self.hintText = hintText if not self.hintText: self.hintText = '' self.hintLabel['text'] = self.hintText if self._FancyLoadingScreen__isVisible(): self.hintLabel.show() def _FancyLoadingScreen__isVisible(self): return self.state def scheduleHide(self, function): base.cr.queueAllInterestsCompleteEvent() self.acceptOnce(function, self.interestComplete) def interestComplete(self): self.endStep('scheduleHide') self.hide() def _FancyLoadingScreen__setAdArt(self): return None imageFrame = self.model.find('**/frame') randomImageNumber = random.randint(0, len(screenShots) - 1) imageFileName = screenShots[randomImageNumber] self.adImage = loader.loadModel(imageFileName) self.adImage.reparentTo(imageFrame) self.adImage.setScale(2.1499999999999999 * 5, 1, 1.2 * 5) self.adImage.setPos(0, 0, 2.2999999999999998) self.adImage.setBin('fixed', 1) if randomImageNumber == 0: urlToGet = 'http://log.go.com/log?srvc=dis&guid=951C36F8-3ACD-4EB2-9F02-8E8A0A217AF5&drop=0&addata=3232:64675:408091:64675&a=0' self.httpSession = HTTPClient() self.nonBlockHTTP = self.httpSession.makeChannel(False) self.nonBlockHTTP.beginGetDocument(DocumentSpec(urlToGet)) instanceMarker = 'FunnelLoggingRequest-%s' % str(random.randint(1, 1000)) self.startCheckingAsyncRequest(instanceMarker) def startCheckingAsyncRequest(self, name): taskMgr.remove(name) taskMgr.doMethodLater(0.5, self.pollAdTask, name) def pollAdTask(self, task): result = self.nonBlockHTTP.run() if result == 0: self.stopCheckingAdTask(task) else: return Task.again def stopCheckingAdTask(self, name): taskMgr.remove(name) def cleanupLoadingScreen(self): if self.debugMode: self.loadingBarRoot.removeChildren() self.cleanupAnalysis() self.stepInfo = { } self.unmappedTicks = [] def showInfo(self, stepName, pos): self.stageLabel['text'] = stepName info = self.stepInfo[stepName] self.tickLabel['text'] = '%s ticks(%s)' % (len(info[3]), info[6]) self.overallLabel['text'] = '%3.2f seconds (%d%%)' % (info[1], 100 * info[1] / (self.loadingEnd - self.loadingStart)) def generateAnalysis(self): if self.analyzeMode: self.cleanupAnalysis() self.analyzeMode = True cm = CardMaker('cm') self.analysisBar.show() loadingTime = self.loadingEnd - self.loadingStart for stepName in self.stepInfo: (startTime, duration, color, ticks, startPercent, percent, expectedTicks) = self.stepInfo[stepName] cm.setName(stepName) cm.setColor(color) cm.setFrame((startTime / loadingTime) * 1.8 - 0.90000000000000002, ((startTime + duration) / loadingTime) * 1.8 - 0.90000000000000002, -0.5, -0.10000000000000001) self.analysisBarRoot.attachNewNode(cm.generate()) button = DirectFrame(parent = self.analysisBarRoot, geom = NodePath('empty'), image = NodePath('empty'), state = DGG.NORMAL, relief = None, frameSize = ((startTime / loadingTime) * 1.8 - 0.90000000000000002, ((startTime + duration) / loadingTime) * 1.8 - 0.90000000000000002, -0.5, -0.10000000000000001)) button.bind(DGG.ENTER, self.showInfo, extraArgs = [ stepName]) self.analysisButtons.append(button) button = DirectFrame(parent = self.analysisBarRoot, geom = NodePath('empty'), image = NodePath('empty'), state = DGG.NORMAL, relief = None, frameSize = ((startPercent / self.loadScale / 100.0) * 1.8 - 0.90000000000000002, ((startPercent + percent) / self.loadScale / 100.0) * 1.8 - 0.90000000000000002, 0.10000000000000001, 0.5)) button.bind(DGG.ENTER, self.showInfo, extraArgs = [ stepName]) self.analysisButtons.append(button) for tick in ticks: self.line.moveTo(VBase3((tick / loadingTime) * 1.8 - 0.90000000000000002, 0, -0.5)) self.line.drawTo(VBase3((tick / loadingTime) * 1.8 - 0.90000000000000002, 0, -0.55000000000000004)) for tick in self.unmappedTicks: self.line.moveTo(VBase3((tick / loadingTime) * 1.8 - 0.90000000000000002, 0, -0.5)) self.line.drawTo(VBase3((tick / loadingTime) * 1.8 - 0.90000000000000002, 0, -0.55000000000000004)) self.analysisSegs = self.analysisBarRoot.attachNewNode(self.line.create()) def cleanupAnalysis(self): for button in self.analysisButtons: button.destroy() self.analysisButtons = [] self.analysisBarRoot.removeChildren() self.analysisBar.hide() self.analyzeMode = False self.analysisSegs = None def adjustSize(self, window): x = max(1, window.getXSize()) y = max(1, window.getYSize()) minSz = min(x, y) aspect = float(x) / y if x > y: self.topLock.setZ(1) else: self.topLock.setZ(float(y) / x) if minSz > IDEALX: self.topLock.setScale(IDEALX / float(x)) elif minSz > IDEALY: self.topLock.setScale(IDEALY / float(y)) else: self.topLock.setScale(1.0)
def TraverserLevelFirst(startNP, funcOpOnNP, *args, **kwargs): npCollection = NodePathCollection() currNP = startNP npCollection.addPath(currNP) notEmtpy = True while notEmtpy: if currNP.countNumDescendants() == 0: # no descendants to add to the stack pass else: # add the currNP's children to stack currChildColl = currNP.getChildren() npCollection.extend(currChildColl) if npCollection.getNumPaths() > 0: # operate on the current node funcOpOnNP(currNP, *args, **kwargs) npCollection.removePath(currNP) # get currNP's sister if npCollection.getNumPaths() > 0: currNP = npCollection.getPath(0) else: notEmtpy = False # scene has been walked in level order currNP = None ####### ####### http://www.panda3d.org/forums/viewtopic.php?t=5817 # Classes and functions for polygons, convex hulls (including # bounding container convex hulls), point-in-polygon test and so on. #import psyco ##psyco.full() #psyco.profile() def isConvex(hull): '''Returns True if the given points form convex hull with vertices in ccw order.''' def _isLeft(q, r, p): return (r[0]-q[0])*(p[1]-q[1]) - (p[0]-q[0])*(r[1]-q[1]) i = -2 j = -1 for k in range(len(hull)): p = hull[i] q = hull[j] r = hull[k] if _isLeft(p, q, r) <= 0: return False i = j j = k return True def monotone_chain(points): '''Returns a convex hull for an unordered group of 2D points. Uses Andrew's Monotone Chain Convex Hull algorithm.''' def _isLeft(q, r, p): return (r[0]-q[0])*(p[1]-q[1]) - (p[0]-q[0])*(r[1]-q[1]) # Remove duplicates (this part of code is useless for Panda's # Point2 or Point3! In their case set() doesn't remove duplicates; # this is why internally this class has all points as (x,y) tuples). points = list(set(points)) # Sort points first by X and then by Y component. points.sort() # Now, points[0] is the lowest leftmost point, and point[-1] is # the highest rightmost point. The line through points[0] and points[-1] # will become dividing line between the upper and the lower groups # of points. p0x, p0y = points[0] p1x, p1y = points[-1] # Initialize upper and lower stacks as empty lists. U = [] L = [] # For each point: for p in points: # First, we check if the point in # i.e. points is left or right or # collinear to the dividing line through points[0] and points[-1]: cross = (p1x-p0x)*(p[1]-p0y) - (p[0]-p0x)*(p1y-p0y) # If the point is lower or colinear, test it for inclusion # into the lower stack. if cross <= 0: # While L contains at least two points and the sequence # of the last two points in L and p does not make # a counter-clockwise turn: while len(L) >= 2 and _isLeft(L[-2], L[-1], p) <= 0: L.pop() L.append(p) # If the point is higher or colinear, test it for inclusion # into the upper stack. if cross >= 0: # While U contains at least two points and the sequence # of the last two points in U and p does not make # a clockwise turn: while len(U) >= 2 and _isLeft(U[-2], U[-1], p) >= 0: U.pop() U.append(p) L.pop() U.reverse() U.pop() return L+U def isLeft(qx, qy, rx, ry, px, py): '''Returns 2D cross product: >0 for p left of the infinite line through q and r, =0 for p on the line, <0 for p right of the line. Requires 6 integers or floats for 3 consecutive points: point1_x, point1_y, point2_x, point2_y, point3_x, point3_y.''' return (rx-qx)*(py-qy) - (px-qx)*(ry-qy) def isLeft2(q, r, p): '''Returns 2D cross product: >0 for p left of the infinite line through q and r, =0 for p on the line, <0 for p right of the line. Requires three consecutive points with (X, Y) as input. If present, Z component is ignored.''' return (r[0]-q[0])*(p[1]-q[1]) - (p[0]-q[0])*(r[1]-q[1]) class AABB2D(): '''Axis-aligned bounding box for 2D shapes. Represents minimum and maximum X and Y coordinates for the contained shape.''' def __init__(self, points): '''To be constructed, AABB requires a list of points with two coordinates (X, Y) each. If present, Z coordinate is ignored.''' self.minX = self.maxX = points[0][0] self.minY = self.maxY = points[0][1] self._calc(points) def _calc(self, points): i = 1 # Not from 0! while i < len(points): px, py = points[i] self.minX = min(self.minX, px) self.maxX = max(self.maxX, px) self.minY = min(self.minY, py) self.maxY = max(self.maxY, py) i += 1 def getCenter(self): '''Returns the center of the AABB.''' x = (self.minX + self.maxX) / 2.0 y = (self.minY + self.maxY) / 2.0 return (x, y) def isInside(self, point): '''Returns True if the given point is inside of this AABB.''' px, py = point if (px - self.minX) * (px - self.maxX) < 0: return False if (py - self.minY) * (py - self.maxY) < 0: return False return True def intersect(self, aabb): '''Tests if this AABB intersects with another AABB. Returns a tuple of values that describe the area of intersection: (leftmost X of intersection, rightmost X of itersection, lowest Y of intersection, highest Y of itersection), or (min X, max X, min Y, max Y). Or 'False' if they don't intersect.''' if self.minX > aabb.maxX or self.maxX < aabb.minX: return False if self.minY > aabb.maxY or self.maxY < aabb.minY: return False minX = max(self.minX, aabb.minX) maxX = min(self.maxX, aabb.maxX) minY = max(self.minY, aabb.minY) maxY = min(self.maxY, aabb.maxY) return (minX, maxX, minY, maxY) class ConvexPolygon(): '''Class for convex polygons in 2D. To be constructed, requires 3 or more different points/vertices. Assumes that polygon is convex, and all vertices are given in counter-clockwise order. Acceptable format for points is "(x, y)", Panda's built-in Point2 or Point3 (but internally they all are transformed into "(x, y)" tuple). It can be used to create a bounding convex hull for an unordered group of points. To do this, pass keyword argument "create=True" to the constructor. Then duplicate and redundant points will be removed and the new "clean" bounding convex hull will be created by applying Andrew's Monotone Chain Convex Hull algorithm: http://www.algorithmist.com/index.php/Monotone_Chain_Convex_Hull''' def __init__(self, *args, **kwargs): '''Pass it least 3 vertices into constructor. Vertices are assumed to be on 2D plane and be given in counter-clockwise order.''' if len(args) == 1: args = args[0] points = [] for v in args: if not (isinstance(v, tuple) or isinstance(v, list)): v = (v[0], v[1]) points.append(v) # Initially, it is assumed that given points are vertices of # a convex hull in ccw order: self.vertices = points if "create" in kwargs: if kwargs["create"]: # Create bounding convex hull: self.vertices = monotone_chain(points) self.numVertices = len(self.vertices) # Create bounding box: self.aabb = AABB2D(self.vertices) def __repr__(self): vl = self.vertices for i in range(self.numVertices): vl[i] = str(vl[i]) res = "\n".join(vl) return res def isInside(self, point): '''Simplified winding number algorithm for convex polys. If the point is within the poly then the endVertex of any edge must always be to the left from the infinite line through point and startVertex. If they are colinear and the point is inside of the AABB of the edge, the point is actually on the edge. Currently, this implementation is the fastest one (2.4 seconds for 1 mln executions on my computer).''' px = point[0] py = point[1] i = -1 j = 0 while j < self.numVertices: qx, qy = self.vertices[i] rx, ry = self.vertices[j] x = (rx-qx)*(py-qy) - (px-qx)*(ry-qy) if x <= 0: if x == 0: # for colinear if (px - qx) * (px - rx) > 0: return False if (py - qy) * (py - ry) > 0: return False return True return False # for right turns i = j j += 1 return True def windingNumber(self, point): '''Winding number point-in-polygon test. Has some difficulties when the point is located on an upward edge. Reference: http://softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm''' def _isLeft(qx, qy, rx, ry, px, py): return (rx-qx)*(py-qy) - (px-qx)*(ry-qy) wn = 0 px = point[0] py = point[1] i = -1 j = 0 while j < self.numVertices: qx, qy = self.vertices[i] rx, ry = self.vertices[j] if (px, py) == (qx, qy): return True if qy <= py: if ry > py: cross = _isLeft(qx, qy, rx, ry, px, py) if cross > 0: wn += 1 else: if ry <= py: cross = _isLeft(qx, qy, rx, ry, px, py) if cross < 0: wn -= 1 i = j j += 1 if wn == 0: return False return True def crossingNumber(self, point): '''Crossing number point-in-polygon test. Has some difficulties when the point is located on an upward edge. Reference: http://softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm''' cn = 0 px = point[0] py = point[1] i = -1 j = 0 while j < self.numVertices: qx, qy = self.vertices[i] rx, ry = self.vertices[j] if (px, py) == (qx, qy): return True if ( ((qy <= py) and (ry > py)) or \ ((qy > py) and (ry <= py)) ): vt = (py - qy) / (ry - qy) if (px < qx + vt * (rx - qx)): cn += 1 i = j j += 1 return cn%2