class State: counter=0 def __init__(self): self.render = None self.render2d = None self.camera = None self.keys = None self.node = NodePath("State"+str(State.counter)+"Node") self.node2d = NodePath("State"+str(State.counter)+"Node2D") State.counter+=1 # OMG so ugly, sorry self.waitTime = 0 def iterate(self): pass def register(self, render, camera, keys, render2d=None): self.render = render self.render2d = render2d self.camera = camera self.keys = keys self.enter() def enter(self): self.node.reparentTo(self.render) if self.render2d: self.node2d.reparentTo(self.render2d) def exit(self): self.node.detachNode() if self.render2d: self.node2d.detachNode()
class CamManager(DirectObject.DirectObject): """1st or 3d person camera, or disable """ def __init__(self, game): self.game = game self.char = self.game.char self.win = self.game.gui.win self.hotkeys = self.game.gui.hotkeys self.node = NodePath('char') self.Ccentr = NodePath('Ccentr') self.Ccentr.reparentTo(self.node) self.Ccentr.setZ(1) self.third_dist = -6 self.sleep = 0.001 self.camera = self.game.gui.camera self.char.reparentTo(self.node) taskMgr.setupTaskChain('cam_move', numThreads = 1, frameSync = False, threadPriority = TPUrgent, timeslicePriority = False) def set_enable(self, value, third = False): self.enable = value self.third = third self.node.reparentTo(self.game.world.root_node) self.node.setPos(self.game.world.avatar.getPos()) if self.enable: self.camera.reparentTo(self.Ccentr) if self.third: self.camera.setPos(0, self.third_dist, 0) #self.char.show() else: self.camera.setPos(0, 0, 0) #self.char.hide() self.camera.lookAt(self.Ccentr) taskMgr.add(self.mouse_update, 'mouse-task') else: self.camera.reparentTo(self.game.world.root_node) self.camera.setPos(self.game.world.root_node, self.game.world.avatar.getPos(self.game.world.root_node)) self.node.detachNode() #@profile_decorator def mouse_update(self, task): """ this task updates the mouse """ if not self.enable: return task.done md = base.win.getPointer(0) x = md.getX() y = md.getY() if self.win.movePointer(0, self.win.getXSize()/2, self.win.getYSize()/2): self.node.setH(self.node.getH() - (x - self.win.getXSize()/2)*0.1) self.Ccentr.setP(self.Ccentr.getP() - (y - self.win.getYSize()/2)*0.1) time.sleep(self.sleep) return task.cont def point_dist(self, p1, p2): return math.sqrt((p1[0]-p2[0])**2+(p1[1]-p2[1])**2+(p1[2]-p2[2])**2)
class DistributedTreasure(DistributedObject): notify = directNotify.newCategory('DistributedTreasure') def __init__(self, cr): DistributedObject.__init__(self, cr) self.grabSoundPath = None self.rejectSoundPath = 'phase_4/audio/sfx/ring_miss.mp3' self.dropShadow = None self.treasureTrack = None self.nodePath = None self.modelPath = None self.modelChildString = None self.sphereRadius = 2.0 self.scale = 1.0 self.zOffset = 0.0 self.playSoundForRemoteToons = True self.fly = True self.shadow = True self.billboard = False self.av = None return def announceGenerate(self): DistributedObject.announceGenerate(self) self.loadModel(self.modelPath, self.modelChildString) self.startAnimation() self.nodePath.reparentTo(render) self.accept(self.uniqueName('entertreasureSphere'), self.handleEnterSphere) def loadModel(self, mdlPath, childString = None): self.grabSound = base.loadSfx(self.grabSoundPath) self.rejectSound = base.loadSfx(self.rejectSoundPath) if self.nodePath == None: self.makeNodePath() else: self.treasure.getChildren().detach() model = loader.loadModel(mdlPath) if childString: model = model.find('**/' + childString) model.instanceTo(self.treasure) return def makeNodePath(self): self.nodePath = NodePath('treasure') if self.billboard: self.nodePath.setBillboardPointEye() self.nodePath.setScale(0.9 * self.scale) self.treasure = self.nodePath.attachNewNode('treasure') if self.shadow: if not self.dropShadow: self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow.bam') self.dropShadow.setColor(0, 0, 0, 0.5) self.dropShadow.setPos(0, 0, 0.025) self.dropShadow.setScale(0.4 * self.scale) self.dropShadow.flattenLight() self.dropShadow.reparentTo(self.nodePath) collSphere = CollisionSphere(0, 0, 0, self.sphereRadius) collSphere.setTangible(0) collNode = CollisionNode(self.uniqueName('treasureSphere')) collNode.setIntoCollideMask(CIGlobals.WallBitmask) collNode.addSolid(collSphere) self.collNodePath = self.nodePath.attachNewNode(collNode) self.collNodePath.stash() def handleEnterSphere(self, collEntry = None): localAvId = base.localAvatar.doId if not self.fly: self.setGrab(localAvId) self.d_requestGrab() def setPosition(self, x, y, z): if not self.nodePath: self.makeNodePath() self.nodePath.reparentTo(render) self.nodePath.setPos(x, y, z + self.zOffset) self.collNodePath.unstash() def setReject(self): self.cleanupTrack() base.playSfx(self.rejectSound, node=self.nodePath) self.treasureTrack = Sequence(LerpColorScaleInterval(self.nodePath, 0.8, colorScale=VBase4(0, 0, 0, 0), startColorScale=VBase4(1, 1, 1, 1), blendType='easeIn'), LerpColorScaleInterval(self.nodePath, 0.2, colorScale=VBase4(1, 1, 1, 1), startColorScale=VBase4(0, 0, 0, 0), blendType='easeOut', name='treasureFlyTrack')) self.treasureTrack.start() def setGrab(self, avId): self.collNodePath.stash() self.avId = avId if self.cr.doId2do.has_key(avId): self.av = self.cr.doId2do[avId] else: self.nodePath.detachNode() return if self.playSoundForRemoteToons or self.avId == base.localAvatar.doId: base.playSfx(self.grabSound, node=self.nodePath) if not self.fly: self.nodePath.detachNode() return self.cleanupTrack() avatarGoneName = self.av.uniqueName('disable') self.accept(avatarGoneName, self.handleUnexpectedExit) flyTime = 1.0 track = Sequence(LerpPosInterval(self.nodePath, flyTime, pos=Point3(0, 0, 3), startPos=self.nodePath.getPos(self.av), blendType='easeInOut'), Func(self.nodePath.detachNode), Func(self.ignore, avatarGoneName)) if self.shadow: self.treasureTrack = Sequence(HideInterval(self.dropShadow), track, ShowInterval(self.dropShadow), name='treasureFlyTrack') else: self.treasureTrack = Sequence(track, name='treasureFlyTrack') self.nodePath.reparentTo(self.av) self.treasureTrack.start() def handleUnexpectedExit(self): self.notify.warning('%s disconnected while collecting treasure.' % str(self.avId)) self.cleanupTrack() def d_requestGrab(self): self.sendUpdate('requestGrab', []) def startAnimation(self): pass def disable(self): self.ignoreAll() self.nodePath.detachNode() DistributedObject.disable(self) def cleanupTrack(self): if self.treasureTrack: self.treasureTrack.finish() self.treasureTrack = None return def delete(self): self.cleanupTrack() DistributedObject.delete(self) self.nodePath.removeNode()
class StaticGeometricModel(object): """ load an object as a static geometric model -> changing pos, rot, color, etc. are not allowed there is no extra elements for this model, thus is much faster author: weiwei date: 20190312 """ def __init__(self, initor=None, name="defaultname", btransparency=True, btwosided=False): """ :param initor: path type defined by os.path or trimesh or nodepath :param btransparency :param name """ if isinstance(initor, StaticGeometricModel): self._objpath = copy.deepcopy(initor.objpath) self._objtrm = copy.deepcopy(initor.objtrm) self._objpdnp = copy.deepcopy(initor.objpdnp) self._name = copy.deepcopy(initor.name) self._localframe = copy.deepcopy(initor.localframe) else: # make a grandma nodepath to separate decorations (-autoshader) and raw nodepath (+autoshader) self._name = name self._objpdnp = NodePath(name) if isinstance(initor, str): self._objpath = initor self._objtrm = da.trm.load(self._objpath) objpdnp_raw = da.trimesh_to_nodepath(self._objtrm, name='pdnp_raw') objpdnp_raw.reparentTo(self._objpdnp) elif isinstance(initor, da.trm.Trimesh): self._objpath = None self._objtrm = initor objpdnp_raw = da.trimesh_to_nodepath(self._objtrm) objpdnp_raw.reparentTo(self._objpdnp) elif isinstance(initor, o3d.geometry.PointCloud ): # TODO should pointcloud be pdnp or pdnp_raw self._objpath = None self._objtrm = da.trm.Trimesh(np.asarray(initor.points)) objpdnp_raw = da.nodepath_from_points(self._objtrm.vertices, name='pdnp_raw') objpdnp_raw.reparentTo(self._objpdnp) elif isinstance( initor, np.ndarray): # TODO should pointcloud be pdnp or pdnp_raw self._objpath = None if initor.shape[1] == 3: self._objtrm = da.trm.Trimesh(initor) objpdnp_raw = da.nodepath_from_points( self._objtrm.vertices) elif initor.shape[1] == 7: self._objtrm = da.trm.Trimesh(initor[:, :3]) objpdnp_raw = da.nodepath_from_points( self._objtrm.vertices, initor[:, 3:].tolist()) objpdnp_raw.setRenderMode(RenderModeAttrib.MPoint, 3) else: # TODO depth UV? raise NotImplementedError objpdnp_raw.reparentTo(self._objpdnp) elif isinstance(initor, o3d.geometry.TriangleMesh): self._objpath = None self._objtrm = da.trm.Trimesh( vertices=initor.vertices, faces=initor.triangles, face_normals=initor.triangle_normals) objpdnp_raw = da.trimesh_to_nodepath(self._objtrm, name='pdnp_raw') objpdnp_raw.reparentTo(self._objpdnp) elif isinstance(initor, NodePath): self._objpath = None self._objtrm = None # TODO nodepath to trimesh? objpdnp_raw = initor objpdnp_raw.reparentTo(self._objpdnp) else: self._objpath = None self._objtrm = None objpdnp_raw = NodePath("pdnp_raw") objpdnp_raw.reparentTo(self._objpdnp) if btransparency: self._objpdnp.setTransparency(TransparencyAttrib.MDual) if btwosided: self._objpdnp.getChild(0).setTwoSided(True) self._localframe = None @property def name(self): # read-only property return self._name @property def objpath(self): # read-only property return self._objpath @property def objpdnp(self): # read-only property return self._objpdnp @property def objpdnp_raw(self): # read-only property return self._objpdnp.getChild(0) @property def objtrm(self): # read-only property # 20210328 comment out, allow None # if self._objtrm is None: # raise ValueError("Only applicable to models with a trimesh!") return self._objtrm @property def localframe(self): # read-only property return self._localframe @property def volume(self): # read-only property if self._objtrm is None: raise ValueError("Only applicable to models with a trimesh!") return self._objtrm.volume def set_rgba(self, rgba): self._objpdnp.setColor(rgba[0], rgba[1], rgba[2], rgba[3]) def get_rgba(self): return da.pdv4_to_npv4( self._objpdnp.getColor()) # panda3d.core.LColor -> LBase4F def clear_rgba(self): self._objpdnp.clearColor() def set_scale(self, scale=[1, 1, 1]): self._objpdnp.setScale(scale[0], scale[1], scale[2]) self._objtrm.apply_scale(scale) def get_scale(self): return da.pdv3_to_npv3(self._objpdnp.getScale()) def set_vert_size(self, size=.005): self.objpdnp_raw.setRenderModeThickness(size * 1000) def attach_to(self, obj): if isinstance(obj, ShowBase): # for rendering to base.render self._objpdnp.reparentTo(obj.render) elif isinstance(obj, StaticGeometricModel ): # prepared for decorations like local frames self._objpdnp.reparentTo(obj.objpdnp) elif isinstance(obj, mc.ModelCollection): obj.add_gm(self) else: print( "Must be ShowBase, modeling.StaticGeometricModel, GeometricModel, CollisionModel, or CollisionModelCollection!" ) def detach(self): self._objpdnp.detachNode() def remove(self): self._objpdnp.removeNode() def show_localframe(self): self._localframe = gen_frame() self._localframe.attach_to(self) def unshow_localframe(self): if self._localframe is not None: self._localframe.remove() self._localframe = None def copy(self): return copy.deepcopy(self)
def create_all_text(self): self.continue_text = OnscreenText(**{ "text": ( "In a moment, you will be asked the question displayed on " "the left. When you are ready, press the spacebar to begin."), "style": 1, "fg": (.75, 0, 0, 1), "bg": self.text_bg, "pos": (.4, .4), "align": TextNode.ACenter, "scale": .08, "font": self.font, "wordwrap": 20 }) self.text_parent = self.continue_text.getParent() self.continue_text.detachNode() xpos = -1.25 skip = .15 self.question_text = OnscreenText(**{ "text": self.question[0], "style": 1, "fg": (0, 0, .8, 1), "bg": self.text_bg, "pos": ((xpos + .05), .8), "align": TextNode.ALeft, "scale": .075, "font": self.font, "wordwrap": 35}) self.question_choice_text = [] for i in xrange(len(self.question[1])): n = len(self.question[1]) - i - 1 ypos = self.choice_text_start - (skip * n) t1 = OnscreenText(**{ "text": "%s" % self.question[1][i][0], "style": 1, "fg": (0, .1, 0, 1), "bg": self.text_bg, "pos": ((xpos + .1), ypos), "align": TextNode.ALeft, "scale": .075, "font": self.font}) t2 = OnscreenText(**{ "text": "%s" % self.question[1][i][1], "style": 1, "fg": (0, .1, 0, 1), "bg": self.text_bg, "pos": ((xpos + 0.17), ypos), "align": TextNode.ALeft, "scale": .05, "font": self.font}) t = NodePath("choice_%s" % i) t.reparentTo(self.text_parent) t1.reparentTo(t) t2.reparentTo(t) self.question_choice_text.append(t) for t in self.question_choice_text: t.detachNode() self.trials_remaining_text = OnscreenText(**{ "text": "", "style": 1, "fg": (0, 0, 0, 1), "bg": self.text_bg, "pos": (-xpos, -.95), "align": TextNode.ARight, "scale": .05, "font": self.font})
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)
class DistributedTreasure(DistributedObject): notify = directNotify.newCategory('DistributedTreasure') def __init__(self, cr): DistributedObject.__init__(self, cr) self.grabSoundPath = None self.rejectSoundPath = 'phase_4/audio/sfx/ring_miss.ogg' self.dropShadow = None self.treasureTrack = None self.nodePath = None self.modelPath = None self.modelChildString = None self.sphereRadius = 2.0 self.scale = 1.0 self.zOffset = 0.0 self.playSoundForRemoteToons = True self.fly = True self.shadow = True self.billboard = False self.av = None self.spinTaskName = None return def announceGenerate(self): DistributedObject.announceGenerate(self) self.spinTaskName = self.uniqueName('treasureRotate') self.loadModel(self.modelPath, self.modelChildString) self.startAnimation() self.nodePath.reparentTo(render) self.accept(self.uniqueName('entertreasureSphere'), self.handleEnterSphere) def loadModel(self, mdlPath, childString=None): self.grabSound = base.loadSfx(self.grabSoundPath) self.rejectSound = base.loadSfx(self.rejectSoundPath) if self.nodePath == None: self.makeNodePath() else: self.treasure.getChildren().detach() model = loader.loadModel(mdlPath) if childString: model = model.find('**/' + childString) model.instanceTo(self.treasure) if self.cr.holidayManager.getHoliday() != 0: self.treasure.setScale(1.5, 1.5, 1.5) self.treasure.setZ(0.8) taskMgr.add(self.__spinTreasure, self.spinTaskName) return def makeNodePath(self): self.nodePath = NodePath('treasure') if self.billboard: self.nodePath.setBillboardPointEye() self.nodePath.setScale(0.9 * self.scale) self.treasure = self.nodePath.attachNewNode('treasure') if self.shadow: if not self.dropShadow: self.dropShadow = loader.loadModel( 'phase_3/models/props/drop_shadow.bam') self.dropShadow.setColor(0, 0, 0, 0.5) self.dropShadow.setPos(0, 0, 0.025) self.dropShadow.setScale(0.4 * self.scale) self.dropShadow.flattenLight() self.dropShadow.reparentTo(self.nodePath) collSphere = CollisionSphere(0, 0, 0, self.sphereRadius) collSphere.setTangible(0) collNode = CollisionNode(self.uniqueName('treasureSphere')) collNode.setIntoCollideMask(CIGlobals.WallBitmask) collNode.addSolid(collSphere) self.collNodePath = self.nodePath.attachNewNode(collNode) self.collNodePath.stash() def __spinTreasure(self, task): self.treasure.setH(20.0 * task.time) return Task.cont def handleEnterSphere(self, collEntry=None): localAvId = base.localAvatar.doId if not self.fly: self.setGrab(localAvId) self.d_requestGrab() def setPosition(self, x, y, z): if not self.nodePath: self.makeNodePath() self.nodePath.reparentTo(render) self.nodePath.setPos(x, y, z + self.zOffset) self.collNodePath.unstash() def setReject(self): self.cleanupTrack() base.playSfx(self.rejectSound, node=self.nodePath) self.treasureTrack = Sequence( LerpColorScaleInterval(self.nodePath, 0.8, colorScale=VBase4(0, 0, 0, 0), startColorScale=VBase4(1, 1, 1, 1), blendType='easeIn'), LerpColorScaleInterval(self.nodePath, 0.2, colorScale=VBase4(1, 1, 1, 1), startColorScale=VBase4(0, 0, 0, 0), blendType='easeOut', name='treasureFlyTrack')) self.treasureTrack.start() def setGrab(self, avId): self.collNodePath.stash() self.avId = avId if self.cr.doId2do.has_key(avId): self.av = self.cr.doId2do[avId] else: self.nodePath.detachNode() return if self.playSoundForRemoteToons or self.avId == base.localAvatar.doId: base.playSfx(self.grabSound, node=self.nodePath) if not self.fly: self.nodePath.detachNode() return self.cleanupTrack() taskMgr.remove(str(self.spinTaskName)) avatarGoneName = self.av.uniqueName('disable') self.accept(avatarGoneName, self.handleUnexpectedExit) flyTime = 1.0 track = Sequence( LerpPosInterval(self.nodePath, flyTime, pos=Point3(0, 0, 3), startPos=self.nodePath.getPos(self.av), blendType='easeInOut'), Func(self.nodePath.detachNode), Func(self.ignore, avatarGoneName)) if self.shadow: self.treasureTrack = Sequence(HideInterval(self.dropShadow), track, ShowInterval(self.dropShadow), name='treasureFlyTrack') else: self.treasureTrack = Sequence(track, name='treasureFlyTrack') self.nodePath.reparentTo(self.av) self.treasureTrack.start() def handleUnexpectedExit(self): self.notify.warning('%s disconnected while collecting treasure.' % str(self.avId)) self.cleanupTrack() def d_requestGrab(self): self.sendUpdate('requestGrab', []) def startAnimation(self): pass def disable(self): self.ignoreAll() self.nodePath.detachNode() DistributedObject.disable(self) def cleanupTrack(self): if self.treasureTrack: self.treasureTrack.finish() self.treasureTrack = None self.spinTaskName = None return def delete(self): self.cleanupTrack() DistributedObject.delete(self) self.nodePath.removeNode()
class VoxelGenerator(DirectObject): def __init__(self, parent, level, chunk_size=(7, 7, 1)): self.parent = parent self.level = level self.node = render.attachNewNode('main_level_node') self.chunk_size = chunk_size self.node_wall_original = NodePath('wall_original') self.node_wall_usable = self.node.attachNewNode("voxgen_wall_usable") self.node_forcewall_usable = self.node.attachNewNode( "voxgen_force_wall_usable") self.node_dynamic_wall_usable = self.node.attachNewNode( "voxgen_dynamic_wall_usable") self.wall_dict = {} self.dynamic_wall_dict = {} # For floors we will create a list of nodepaths, each list member will parent one chunk of tiles x = int((level.maxX - 1) / chunk_size[0]) + 1 y = int((level.maxY - 1) / chunk_size[1]) + 1 self.floor_np = NodePath("voxgen_floor_original") self.floor_usable_np = self.node.attachNewNode("voxgen_floor_usable") self.floor_np_list = [] self.floor_usable_np_list = [] for i in xrange(x): temp_list = [] temp_list_usable = [] for j in xrange(y): n = self.floor_np.attachNewNode('n_' + str(i) + '_' + str(j)) temp_list.append(n) n2 = self.floor_usable_np.attachNewNode('n_usable_' + str(i) + '_' + str(j)) temp_list_usable.append(n2) self.floor_np_list.append(temp_list) self.floor_usable_np_list.append(temp_list_usable) self.floor_tile_dict = {} # We need a FIFO struct to hold pointers to dirty chunks that need flattening self.dirty_chunks = deque() self.dirty_walls = 0 self.old_tile_dict = None self.old_invisible_walls = [] # Create flatten task self.pause_flatten_task = True self.frames_between = 3 self.frames_counter = 0 taskMgr.add(self.flattenTask, "flatten_task") self.grid_display = False self.createGrid() self.accept('z', self.toggleGrid) def createGrid(self): segs = LineSegs() segs.setThickness(4.0) segs.setColor(Vec4(1, 1, 0, 0.3)) for i in xrange(self.level.maxX): segs.moveTo(i + 1, 0, utils.GROUND_LEVEL) segs.drawTo(i + 1, self.level.maxY, utils.GROUND_LEVEL + 0.02) for j in xrange(self.level.maxY): segs.moveTo(0, j + 1, utils.GROUND_LEVEL) segs.drawTo(self.level.maxX, j + 1, utils.GROUND_LEVEL + 0.02) self.grid = NodePath(segs.create()) self.grid.setTransparency(TransparencyAttrib.MAlpha) def toggleGrid(self): if not self.grid_display: self.grid.reparentTo(self.node) self.grid_display = True else: self.grid.detachNode() self.grid_display = False def markChunkDirty(self, x, y): chunk_x = int(x / self.chunk_size[0]) chunk_y = int(y / self.chunk_size[0]) payload = (self.floor_np_list[chunk_x][chunk_y], chunk_x, chunk_y) if not payload in self.dirty_chunks: self.dirty_chunks.append(payload) def markAllChunksDirty(self): self.pause_flatten_task = True for idx, val in enumerate(self.floor_np_list): for idy, v in enumerate(val): payload = self.floor_np_list[idx][idy], idx, idy self.dirty_chunks.append(payload) self.pause_flatten_task = False def createLevel(self): self.tex1 = loader.loadTexture("tile1.png") self.tex2 = loader.loadTexture("tile2.png") self.tex3 = loader.loadTexture("tile3.png") self.tex_tile_nm = loader.loadTexture("tile2nm.png") self.tex_fs = loader.loadTexture("rnbw.png") self.ts_fs = TextureStage('ts_fs') self.tex1.setMagfilter(Texture.FTLinearMipmapLinear) self.tex1.setMinfilter(Texture.FTLinearMipmapLinear) self.tex2.setMagfilter(Texture.FTLinearMipmapLinear) self.tex2.setMinfilter(Texture.FTLinearMipmapLinear) self.tex3.setMagfilter(Texture.FTLinearMipmapLinear) self.tex3.setMinfilter(Texture.FTLinearMipmapLinear) self.tex_tile_nm.setMagfilter(Texture.FTLinearMipmapLinear) self.tex_tile_nm.setMinfilter(Texture.FTLinearMipmapLinear) ts = TextureStage('ts') for x in xrange(0, self.level.maxX): for y in xrange(0, self.level.maxY): if self.level.getHeight((x, y)) == 0: model = loader.loadModel('flattile') model.setScale(utils.TILE_SIZE) model.setPos(x * utils.TILE_SIZE, y * utils.TILE_SIZE, utils.GROUND_LEVEL) """ if (x == 0 or x == self.level.maxX-1) or (y==0 or y==self.level.maxY-1): model = loader.loadModel('halfcube') model.setScale(utils.TILE_SIZE) model.setPos(x*utils.TILE_SIZE, y*utils.TILE_SIZE, utils.GROUND_LEVEL) else: model = loader.loadModel('flattile') model.setScale(utils.TILE_SIZE) model.setPos(x*utils.TILE_SIZE, y*utils.TILE_SIZE, utils.GROUND_LEVEL) """ #model = loader.loadModel('halfcube') #model.setPos(x, y, 0) model.reparentTo(self.floor_np_list[int( x / self.chunk_size[0])][int(y / self.chunk_size[1])]) self.floor_tile_dict[(x, y)] = model elif self.level.getHeight((x, y)) == 1: model = loader.loadModel('halfcube') model.setScale(utils.TILE_SIZE) model.setPos(x * utils.TILE_SIZE, y * utils.TILE_SIZE, 0) model.reparentTo(self.floor_np_list[int( x / self.chunk_size[0])][int(y / self.chunk_size[1])]) self.floor_tile_dict[(x, y)] = model model = loader.loadModel('halfcube') model.setScale(utils.TILE_SIZE) model.setPos(x * utils.TILE_SIZE, y * utils.TILE_SIZE, utils.GROUND_LEVEL) model.setTexture(ts, self.tex1) #model.setTexture(self.ts_nm, self.tex_tile_nm) model.reparentTo(self.node_wall_original) else: for i in xrange(0, self.level.getHeight((x, y))): if i == 0: if (x == 0 or x == self.level.maxX - 1) or (y == 0 or y == self.level.maxY - 1): model = loader.loadModel('halfcube') model.setScale(utils.TILE_SIZE) model.setPos(x * utils.TILE_SIZE, y * utils.TILE_SIZE, utils.GROUND_LEVEL) else: model = loader.loadModel('flattile') model.setScale(utils.TILE_SIZE) model.setPos(x * utils.TILE_SIZE, y * utils.TILE_SIZE, utils.GROUND_LEVEL) model.reparentTo(self.floor_np_list[int( x / self.chunk_size[0])][int( y / self.chunk_size[1])]) self.floor_tile_dict[(x, y)] = model else: model = loader.loadModel('cube') model.setScale(utils.TILE_SIZE) model.setPos( x * utils.TILE_SIZE, y * utils.TILE_SIZE, (i - 1) * utils.TILE_SIZE + utils.GROUND_LEVEL) model.setTexture(ts, self.tex2) #model.setTexture(self.ts_nm, self.tex_tile_nm) model.reparentTo(self.node_wall_original) self.floor_np.setTexture(self.tex3) #Calculate and place walls between tiles for x, val in enumerate(self.level._grid): for y, val2 in enumerate(val): if val2 != None: # prvi parni, drugi neparni tile2_x, tile2_y, h = self.getWallPosition(x, y) if tile2_x == None: continue my_x = tile2_x my_y = tile2_y if val2.name == "Wall1": model = loader.loadModel("wall") model.setScale(utils.TILE_SIZE) model.setPos(my_x * utils.TILE_SIZE, my_y * utils.TILE_SIZE, utils.GROUND_LEVEL) model.setH(h) self.wall_dict[(my_x, my_y, h)] = model model.reparentTo(self.node_wall_original) elif val2.name == "Wall2": model = loader.loadModel("wall2") model.setScale(utils.TILE_SIZE) model.setPos(my_x * utils.TILE_SIZE, my_y * utils.TILE_SIZE, utils.GROUND_LEVEL) model.setH(h) model.setColor(0, 1, 0, 1) self.wall_dict[(my_x, my_y, h)] = model model.reparentTo(self.node_wall_original) elif val2.name == "HalfWall": model = loader.loadModel("wall2") model.setScale(utils.TILE_SIZE) model.flattenLight() model.setPos(my_x * utils.TILE_SIZE, my_y * utils.TILE_SIZE, utils.GROUND_LEVEL) model.setH(h) model.setColor(0, 0, 0, 1) model.setScale(1, 1, 0.4) self.wall_dict[(my_x, my_y, h)] = model model.reparentTo(self.node_wall_original) elif val2.name == "Ruin": model = loader.loadModel("wall2") model.setScale(utils.TILE_SIZE) model.setPos(my_x * utils.TILE_SIZE, my_y * utils.TILE_SIZE, utils.GROUND_LEVEL) model.setH(h) model.setColor(0.5, 0.8, 1, 0.6) model.setTransparency(TransparencyAttrib.MAlpha) model.reparentTo(self.node_forcewall_usable) s = Sequence( LerpColorInterval(model, 1, (0.13, 0.56, 0.78, 0.6)), LerpColorInterval(model, 1, (0.5, 0.8, 1, 0.6)), ) s.loop() model.setLightOff() elif val2.name == "ClosedDoor": model = loader.loadModel("door") model.setScale(utils.TILE_SIZE) model.setPos(my_x * utils.TILE_SIZE, my_y * utils.TILE_SIZE, utils.GROUND_LEVEL) model.setH(h) model.setColor(1, 0.0, 0, 0.0) self.dynamic_wall_dict[(my_x, my_y, h)] = model model.reparentTo(self.node_dynamic_wall_usable) elif val2.name == "OpenedDoor": model = loader.loadModel("door") model.setScale(utils.TILE_SIZE) model.setPos(my_x * utils.TILE_SIZE, my_y * utils.TILE_SIZE, utils.GROUND_LEVEL) model.setH(h) model.setScale(0.2, 1, 1) model.setColor(0.7, 0.2, 0.2, 0.0) self.dynamic_wall_dict[(my_x, my_y, h)] = model model.reparentTo(self.node_dynamic_wall_usable) elif val2.name == "ForceField": model = loader.loadModel("wall_fs") model.setScale(utils.TILE_SIZE) model.setPos(my_x * utils.TILE_SIZE, my_y * utils.TILE_SIZE, utils.GROUND_LEVEL) model.setH(h) model.setTexture(self.ts_fs, self.tex_fs) model.setTransparency(TransparencyAttrib.MAlpha) model.reparentTo(self.node_forcewall_usable) self.dynamic_wall_dict[(my_x, my_y, h)] = model model.setLightOff() #self.floor_usable_np.setShaderAuto() self.floor_usable_np.setTexture(self.tex3) self.markAllChunksDirty() self.dirty_walls = 1 def getWallPosition(self, x, y): if (x % 2 == 0 and y % 2 != 0): pos_x = x / 2 pos_y = (y - 1) / 2 h = 90 # prvi neparni, drugi parni elif (x % 2 != 0 and y % 2 == 0): pos_x = (x - 1) / 2 pos_y = y / 2 h = 0 else: pos_x = None pos_y = None h = None return pos_x, pos_y, h def processLevel(self, invisible_walls): self.level = self.parent.parent.level for x, val in enumerate(self.level._grid): for y, val2 in enumerate(val): if val2 != None: my_x, my_y, h = self.getWallPosition(x, y) # prvi parni, drugi neparni if my_x == None: continue if val2.name == "ClosedDoor" and val2.name != self.parent.parent.old_level._grid[ x][y].name: if not (x, y) in self.old_invisible_walls: self.dynamic_wall_dict[(my_x, my_y, h)].setScale(1) else: i = self.dynamic_wall_dict[(my_x, my_y, h)].scaleInterval( 1, Vec3(1, 1, 1)) i.start() elif val2.name == "OpenedDoor" and val2.name != self.parent.parent.old_level._grid[ x][y].name: if not (x, y) in self.old_invisible_walls: self.dynamic_wall_dict[(my_x, my_y, h)].setScale(0.2, 1, 1) else: i = self.dynamic_wall_dict[(my_x, my_y, h)].scaleInterval( 1, Vec3(0.2, 1, 1)) i.start() self.old_invisible_walls = invisible_walls def setInvisibleTilesInThread(self): taskMgr.add(self.setInvisibleTiles, 'invis_tiles', extraArgs=[], taskChain='thread_1') def setInvisibleTiles(self): tile_dict = self.parent.parent.getInvisibleTiles() for invisible_tile in tile_dict: if self.old_tile_dict == None or tile_dict[ invisible_tile] != self.old_tile_dict[invisible_tile]: if tile_dict[invisible_tile] == 0: self.floor_tile_dict[invisible_tile].setColorScale( 0.3, 0.3, 0.3, 1) self.markChunkDirty(invisible_tile[0], invisible_tile[1]) else: self.floor_tile_dict[invisible_tile].setColorScale( 1, 1, 1, 1) self.markChunkDirty(invisible_tile[0], invisible_tile[1]) self.old_tile_dict = tile_dict def setInvisibleWallsInThread(self): taskMgr.add(self.setInvisibleWalls, 'invis_walls', extraArgs=[], taskChain='thread_1') def setInvisibleWalls(self): visible_wall_list = self.parent.parent.getInvisibleWalls() self.processLevel(visible_wall_list) new_list = [] for l in visible_wall_list: x, y, h = self.getWallPosition(l[0], l[1]) new_list.append((x, y, h)) for wall in self.wall_dict: # If we have key in visible_wall_dict, the wall is visible if wall in new_list: self.wall_dict[wall].setColorScale(1, 1, 1, 1) else: self.wall_dict[wall].setColorScale(0.3, 0.3, 0.3, 1) for wall in self.dynamic_wall_dict: if wall in new_list: self.dynamic_wall_dict[wall].setColorScale(1, 1, 1, 1) else: self.dynamic_wall_dict[wall].setColorScale(0.3, 0.3, 0.3, 1) self.dirty_walls = 1 def flattenTask(self, task): if self.pause_flatten_task: return task.cont if self.frames_counter < self.frames_between: self.frames_counter += 1 if self.dirty_walls == 1: np = self.node_wall_original.copyTo(NodePath()) np.clearModelNodes() np.flattenStrong() self.node_wall_usable.removeNode() self.node_wall_usable = np self.node_wall_usable.reparentTo(self.node) #self.node_wall_usable.setShaderAuto() self.dirty_walls = 0 if len(self.dirty_chunks) > 0: if self.frames_counter == self.frames_between: chunk_tupple = self.dirty_chunks.popleft() np = chunk_tupple[0].copyTo(NodePath()) np.clearModelNodes() np.flattenStrong() self.floor_usable_np_list[chunk_tupple[1]][ chunk_tupple[2]].removeNode() self.floor_usable_np_list[chunk_tupple[1]][ chunk_tupple[2]] = np self.floor_usable_np_list[chunk_tupple[1]][ chunk_tupple[2]].reparentTo(self.floor_usable_np) self.frames_counter = 0 return task.cont
class LineDrawer: def __init__(self, game, color = (1,0.1,0.1,0.0)): self.game = game self.node = GeomNode("lines") self.np = NodePath(self.node) self.np.reparentTo(self.game.render) self.np.setShaderOff() self.np.setLightOff() self.color = color self.np.setColor(self.color) self.path = [] self.start = (0, 0) self.end = (0, 0) def setStart(self, start): self.start = start #self.startModel.setPos(start[0]+0.5, start[1]+0.5, 0) def setEnd(self, end): self.end = end #self.endModel.setPos(end[0]+0.5, end[1]+0.5, 0) def clear(self): self.np.remove() self.node = GeomNode("lines") self.np = NodePath(self.node) self.np.reparentTo(self.game.render) self.np.setShaderOff() self.np.setLightOff() self.np.setColor(self.color) def destroy(self): self.np.detachNode() del self.np def drawLine(self, start, end): #print "Draw line : %s, %s" % (str(start), str(end)) self.node.addGeom(self.line(start, end)) def line (self, start, end): # since we're doing line segments, just vertices in our geom format = GeomVertexFormat.getV3() # build our data structure and get a handle to the vertex column vdata = GeomVertexData ('', format, Geom.UHStatic) vertices = GeomVertexWriter (vdata, 'vertex') # build a linestrip vertex buffer lines = GeomLinestrips (Geom.UHStatic) vertices.addData3f (start[0], start[1], start[2]) vertices.addData3f (end[0], end[1], end[2]) lines.addVertices (0, 1) lines.closePrimitive() geom = Geom (vdata) geom.addPrimitive (lines) # Add our primitive to the geomnode #self.gnode.addGeom (geom) return geom def setPath(self, path): self.path = path self.clear() for pos in range(len(self.path)-1): self.drawLine(self.path[pos], self.path[pos+1])
class BaseObject(BaseRunnable): """ BaseObject is something interacting with game engine. If something is expected to have a body in the world or have appearance in the world, it must be a subclass of BaseObject. It is created with name/config/randomEngine and can make decision in the world. Besides the random engine can help sample some special configs for it ,Properties and parameters in PARAMETER_SPACE of the object are fixed after calling __init__(). """ def __init__(self, name=None, random_seed=None, config=None, escape_random_seed_assertion=False): """ Config is a static conception, which specified the parameters of one element. There parameters doesn't change, such as length of straight road, max speed of one vehicle, etc. """ super(BaseObject, self).__init__(name, random_seed, config) if not escape_random_seed_assertion: assert random_seed is not None, "Please assign a random seed for {} class.".format( self.class_name) # Following properties are available when this object needs visualization and physics property self._body = None # each element has its node_path to render, physics node are child nodes of it self.origin = NodePath(self.name) # Temporally store bullet nodes that have to place in bullet world (not NodePath) self.dynamic_nodes = PhysicsNodeList() # Nodes in this tuple didn't interact with other nodes! they only used to do rayTest or sweepTest self.static_nodes = PhysicsNodeList() # render or not self.render = False if AssetLoader.loader is None else True if self.render: self.loader = AssetLoader.get_loader() if not hasattr(self.loader, "loader"): # It is closed before! self.loader.__init__() def add_body(self, physics_body): if self._body is None: # add it to physics world, in which this object will interact with other object (like collision) if not isinstance(physics_body, BulletBodyNode): raise ValueError("The physics body is not BulletBodyNode type") self._body = physics_body new_origin = NodePath(self._body) self.origin.getChildren().reparentTo(new_origin) self.origin = new_origin self.dynamic_nodes.append(physics_body) else: raise AttributeError("You can not set the object body for twice") @property def body(self): if self._body.hasPythonTag(self._body.getName()): return self._body.getPythonTag(self._body.getName()) else: return self._body def attach_to_world(self, parent_node_path: NodePath, physics_world: PhysicsWorld): """ Load to world from memory """ if self.render: # double check :-) assert isinstance( self.origin, NodePath), "No render model on node_path in this Element" self.origin.reparentTo(parent_node_path) self.dynamic_nodes.attach_to_physics_world(physics_world.dynamic_world) self.static_nodes.attach_to_physics_world(physics_world.static_world) def detach_from_world(self, physics_world: PhysicsWorld): """ It is not fully remove, it will be left in memory. if this element is useless in the future, call Func delete() """ if self.origin is not None: self.origin.detachNode() self.dynamic_nodes.detach_from_physics_world( physics_world.dynamic_world) self.static_nodes.detach_from_physics_world(physics_world.static_world) def destroy(self): """ Fully delete this element and release the memory """ from pgdrive.engine.engine_utils import get_engine engine = get_engine() self.detach_from_world(engine.physics_world) if self._body is not None and hasattr(self.body, "object"): self.body.generated_object = None if self.origin is not None: self.origin.removeNode() self.dynamic_nodes.clear() self.static_nodes.clear() self._config.clear()
class ARObject(object): NOTHING = object() def __init__(self, *args): self.args= args self.mainNP= NodePath('ARObject') self.bulletNodes= [] self.junctionPoints= [] #Position as 3 floats def setPos(self, X, Y, Z): self.mainNP.setPos(X,Y,Z) #Position as one Point3 def setPos(self, Pos): self.mainNP.setPos(Pos) #HPR as 3 floats def setHpr(self, H, P, R): self.mainNP.setHpr(H,P,R) #HPR as a VBase3 def setHpr(self, Hpr): self.mainNP.setHpr(Hpr) def reparentTo(self, NP, world): #Adding bullet ridig bodies to the world for x in self.bulletNodes: world.attachRigidBody(x) self.mainNP.reparentTo(NP) def detach(self, world): #Removing bullet ridig bodies from the world for x in self.bulletNodes: world.removeRigidBody(x) self.mainNP.detachNode() def addBulletNode(self, name, *shapes): bulletNode= BulletRigidBodyNode(name) bulletNode.setDeactivationEnabled(False) for x in shapes: bulletNode.addShape(x) self.bulletNodes.append(bulletNode) self.mainNP.attachNewNode(bulletNode) return bulletNode def setMass(self): self.bulletNodes[0].setMass(self.args[0]) def setMassZero(self): self.bulletNodes[0].setMass(0) def NormalizeVector(self, myVec): myVec.normalize() return myVec def makeSquare(self, x1,y1,z1, x2,y2,z2, colorVec=Vec4(1.0,1.0,1.0,1.0), texFunction= NOTHING, colorFunction= NOTHING ): vertexformat=GeomVertexFormat.getV3n3cpt2() vdata=GeomVertexData('square', vertexformat, Geom.UHDynamic) vertex=GeomVertexWriter(vdata, 'vertex') normal=GeomVertexWriter(vdata, 'normal') color=GeomVertexWriter(vdata, 'color') texcoord=GeomVertexWriter(vdata, 'texcoord') #make sure we draw the square in the right plane if x1!=x2: vertex.addData3f(x1, y1, z1) vertex.addData3f(x2, y1, z1) vertex.addData3f(x2, y2, z2) vertex.addData3f(x1, y2, z2) normal.addData3f(self.NormalizeVector(Vec3(2*x1-1, 2*y1-1, 2*z1-1))) normal.addData3f(self.NormalizeVector(Vec3(2*x2-1, 2*y1-1, 2*z1-1))) normal.addData3f(self.NormalizeVector(Vec3(2*x2-1, 2*y2-1, 2*z2-1))) normal.addData3f(self.NormalizeVector(Vec3(2*x1-1, 2*y2-1, 2*z2-1))) else: vertex.addData3f(x1, y1, z1) vertex.addData3f(x2, y2, z1) vertex.addData3f(x2, y2, z2) vertex.addData3f(x1, y1, z2) normal.addData3f(self.NormalizeVector(Vec3(2*x1-1, 2*y1-1, 2*z1-1))) normal.addData3f(self.NormalizeVector(Vec3(2*x2-1, 2*y2-1, 2*z1-1))) normal.addData3f(self.NormalizeVector(Vec3(2*x2-1, 2*y2-1, 2*z2-1))) normal.addData3f(self.NormalizeVector(Vec3(2*x1-1, 2*y1-1, 2*z2-1))) if(colorFunction == ARObject.NOTHING): self.addColor(color, colorVec) else: colorFunction(color,colorVec) if(texFunction == ARObject.NOTHING): self.addTexCoord(texcoord, x1,y1,z1, x2,y2,z2) else: texFunction(texcoord, x1,y1,z1, x2,y2,z2) tri1=GeomTriangles(Geom.UHDynamic) tri2=GeomTriangles(Geom.UHDynamic) tri1.addVertex(0) tri1.addVertex(1) tri1.addVertex(3) tri2.addConsecutiveVertices(1,3) tri1.closePrimitive() tri2.closePrimitive() square=Geom(vdata) square.addPrimitive(tri1) square.addPrimitive(tri2) return square def addColor(self, color, colorVec): color.addData4f(colorVec) color.addData4f(colorVec) color.addData4f(colorVec) color.addData4f(colorVec) def addTexCoord(self, texcoord, x1,y1,z1, x2,y2,z2): texcoord.addData2f(0.0, 1.0) texcoord.addData2f(0.0, 0.0) texcoord.addData2f(1.0, 0.0) texcoord.addData2f(1.0, 1.0) def __del__(self): print "Instance of Class ", self.__class__.__name__ ," Removed."
def create_all_text(self): self.continue_text = OnscreenText( **{ "text": ("In a moment, you will be asked the question displayed on " "the left. When you are ready, press the spacebar to begin." ), "style": 1, "fg": (.75, 0, 0, 1), "bg": self.text_bg, "pos": (.4, .4), "align": TextNode.ACenter, "scale": .08, "font": self.font, "wordwrap": 20 }) self.text_parent = self.continue_text.getParent() self.continue_text.detachNode() xpos = -1.25 skip = .15 self.question_text = OnscreenText( **{ "text": self.question[0], "style": 1, "fg": (0, 0, .8, 1), "bg": self.text_bg, "pos": ((xpos + .05), .8), "align": TextNode.ALeft, "scale": .075, "font": self.font, "wordwrap": 35 }) self.question_choice_text = [] for i in xrange(len(self.question[1])): n = len(self.question[1]) - i - 1 ypos = self.choice_text_start - (skip * n) t1 = OnscreenText( **{ "text": "%s" % self.question[1][i][0], "style": 1, "fg": (0, .1, 0, 1), "bg": self.text_bg, "pos": ((xpos + .1), ypos), "align": TextNode.ALeft, "scale": .075, "font": self.font }) t2 = OnscreenText( **{ "text": "%s" % self.question[1][i][1], "style": 1, "fg": (0, .1, 0, 1), "bg": self.text_bg, "pos": ((xpos + 0.17), ypos), "align": TextNode.ALeft, "scale": .05, "font": self.font }) t = NodePath("choice_%s" % i) t.reparentTo(self.text_parent) t1.reparentTo(t) t2.reparentTo(t) self.question_choice_text.append(t) for t in self.question_choice_text: t.detachNode() self.trials_remaining_text = OnscreenText( **{ "text": "", "style": 1, "fg": (0, 0, 0, 1), "bg": self.text_bg, "pos": (-xpos, -.95), "align": TextNode.ARight, "scale": .05, "font": self.font })
class Movement(DirectObject.DirectObject): def __init__(self, parent): self.parent = parent self.hovered_unit_id = None self.hovered_tile = None self.hovered_compass_tile = None self.mouse_node = aspect2d.attachNewNode('mouse_node') self.move_node = aspect2d.attachNewNode('move_node') self.move_outline_node = NodePath('') self.move_np_list = [] self.target_info_node = None self.accept("mouse1", self.mouseLeftClick) self.accept("mouse1-up", self.mouseLeftClickUp) #taskMgr.add(self.rayupdate, 'rayupdate_task') taskMgr.add(self.pickerTask, 'picker_task') taskMgr.add(self.positionTask, 'position_task', sort=2) self.color_scale_parallel = None # Create movement compass nodes self.turn_node = NodePath('turn_node') self.turn_node.setTag('show', '0') self.turn_np_list = [] for i in xrange(9): text = TextNode('node name') text.setAlign(TextNode.ACenter) if i == 0: text.setText('NW') key = utils.HEADING_NW elif i == 1: text.setText('N') key = utils.HEADING_N elif i == 2: text.setText('NE') key = utils.HEADING_NE elif i == 3: text.setText('W') key = utils.HEADING_W elif i == 4: text.setText('E') key = utils.HEADING_E elif i == 5: text.setText('SW') key = utils.HEADING_SW elif i == 6: text.setText('S') key = utils.HEADING_S elif i == 7: text.setText('SE') key = utils.HEADING_SE elif i == 8: text.setText('X') key = utils.HEADING_NONE textNodePath = self.turn_node.attachNewNode(text) textNodePath.setColor(1, 1, 1) textNodePath.setScale(0.06) textNodePath.setTag('key', str(key)) self.turn_np_list.append(textNodePath) def calcUnitAvailMove(self, unit_id): """Displays visual indicator of tiles which are in movement range of the selected unit.""" # First delete old movement list for c in self.move_np_list: c.removeNode() self.move_np_list = [] # Start calculation of new list unit = self.parent.local_engine.units[unit_id] if self.parent.turn_player != self.parent.player_id: return if unit: unit['move_dict'] = getMoveDict(unit, self.parent.local_engine.level, self.parent.local_engine.units) self.parent.local_engine.units[unit_id]['move_dict'] = unit[ 'move_dict'] move_dict = unit['move_dict'] for tile in move_dict: text = TextNode('node name') text.setText("%s" % move_dict[tile]) text.setAlign(TextNode.ACenter) textNodePath = self.move_node.attachNewNode(text) textNodePath.setColor(1, 1, 1) textNodePath.setScale(0.06) textNodePath.setPythonTag('pos', tile) pos2d = utils.pointCoordIn2d( Point3(utils.TILE_SIZE * (tile[0] + 0.5), utils.TILE_SIZE * (tile[1] + 0.5), utils.GROUND_LEVEL)) textNodePath.setPos(pos2d) self.move_np_list.append(textNodePath) def showUnitAvailMove(self): self.move_node.reparentTo(aspect2d) self.hovered_tile = None #self.drawMoveOutline(self.calcMoveOutline(move_dict, self.parent.local_engine.units[unit_id]['pos'])) def hideUnitAvailMove(self): self.move_node.detachNode() """ def calcMoveOutline(self, move_dict, pos): outline = {} for tile in move_dict: dir = [] if not (tile[0]-1, tile[1]) in move_dict and (tile[0]-1, tile[1]) != pos: dir.append('W') if not (tile[0], tile[1]-1) in move_dict and (tile[0], tile[1]-1) != pos: dir.append('S') if not (tile[0]+1, tile[1]) in move_dict and (tile[0]+1, tile[1]) != pos: dir.append('E') if not (tile[0], tile[1]+1) in move_dict and (tile[0], tile[1]+1) != pos: dir.append('N') if dir != []: outline[tile] = dir return outline def drawMoveOutline(self, outline): self.move_outline_node.removeNode() zpos = utils.GROUND_LEVEL + 0.01 off = 0.1 segs = LineSegs() segs.setThickness(3) segs.setColor(Vec4(0.686,1,0.992,1)) for tile in outline: for dir in outline[tile]: if dir == 'N': d1 = 0 d2 = 0 if (tile[0]+1, tile[1]) in outline and 'N' in outline[(tile[0]+1, tile[1])]: d2 = off elif (tile[0]+1, tile[1]+1) in outline: d2 = 2*off if (tile[0]-1, tile[1]) in outline and 'N' in outline[(tile[0]-1, tile[1])]: d1 = off elif (tile[0]-1, tile[1]+1) in outline: d1 = 2*off segs.moveTo(tile[0]+off-d1, tile[1]+1-off, zpos) segs.drawTo(tile[0]+1-off+d2, tile[1]+1-off, zpos) elif dir == 'S': d1 = 0 d2 = 0 if (tile[0]+1, tile[1]) in outline and 'S' in outline[(tile[0]+1, tile[1])]: d2 = off elif (tile[0]+1, tile[1]-1) in outline: d2 = 2*off if (tile[0]-1, tile[1]) in outline and 'S' in outline[(tile[0]-1, tile[1])]: d1 = off elif (tile[0]-1, tile[1]-1) in outline: d1 = 2*off segs.moveTo(tile[0]+off-d1, tile[1]+off, zpos) segs.drawTo(tile[0]+1-off+d2, tile[1]+off, zpos) elif dir == 'W': d1 = 0 d2 = 0 if (tile[0], tile[1]+1) in outline and 'W' in outline[(tile[0], tile[1]+1)]: d2 = off elif (tile[0]-1, tile[1]+1) in outline: d2 = 2*off if (tile[0], tile[1]-1) in outline and 'W' in outline[(tile[0], tile[1]-1)]: d1 = off elif (tile[0]-1, tile[1]-1) in outline: d1 = 2*off segs.moveTo(tile[0]+off, tile[1]+off-d1, zpos) segs.drawTo(tile[0]+off, tile[1]+1-off+d2, zpos) elif dir == 'E': d1 = 0 d2 = 0 if (tile[0], tile[1]+1) in outline and 'E' in outline[(tile[0], tile[1]+1)]: d2 = off elif (tile[0]+1, tile[1]+1) in outline: d2 = 2*off if (tile[0], tile[1]-1) in outline and 'E' in outline[(tile[0], tile[1]-1)]: d1 = off elif (tile[0]+1, tile[1]-1) in outline: d1 = 2*off segs.moveTo(tile[0]+1-off, tile[1]+off-d1, zpos) segs.drawTo(tile[0]+1-off, tile[1]+1-off+d2, zpos) self.move_outline_node = render.attachNewNode(segs.create()) self.move_outline_node.setBin("fixed", 40) #self.move_outline_node.setDepthTest(False) #self.move_outline_node.setDepthWrite(False) self.move_outline_node.setLightOff() """ def showMoveCompass(self, dest): # Calculate postion of compass nodes based on destination tile for i in self.turn_np_list: i.setPythonTag('pos', utils.getHeadingTile(i.getTag('key'), dest)) # Show compass nodes self.turn_node.reparentTo(aspect2d) self.turn_node.setPythonTag('pos', dest) self.turn_node.setTag('show', '1') # Hide move nodes self.move_node.detachNode() def hideMoveCompass(self): # Hide compass nodes self.turn_node.detachNode() self.turn_node.setTag('show', '0') if self.hovered_compass_tile != None: self.hovered_compass_tile.setColor(1, 1, 1) self.hovered_compass_tile.setScale(0.05) self.color_scale_parallel.pause() self.hovered_compass_tile = None def mouseLeftClick(self): if self.parent.interface.hovered_gui != None: return if self.hovered_unit_id != None: unit_id = int(self.hovered_unit_id) pickedCoord = self.parent.local_engine.getCoordsByUnit(unit_id) # Player can only select his own units if self.parent.local_engine.isThisMyUnit(unit_id): if unit_id != self.parent.sel_unit_id: self.parent.selectUnit(unit_id) else: # Remember movement tile so we can send orientation message when mouse is depressed # Do this only if it is our turn if self.parent.player_id == self.parent.turn_player: self.unit_move_destination = pickedCoord self.showMoveCompass(self.unit_move_destination) elif self.parent.local_engine.isThisEnemyUnit(unit_id): if self.parent.sel_unit_id != None and self.parent.player_id == self.parent.turn_player: self.parent.render_manager.unit_renderer_dict[ self.parent. sel_unit_id].target_unit = self.parent.render_manager.unit_renderer_dict[ unit_id] if self.parent._anim_in_process == False: ClientMsg.shoot(self.parent.sel_unit_id, unit_id) elif self.hovered_tile != None: if self.parent.sel_unit_id != None and self.parent.player_id == self.parent.turn_player: # Remember movement tile so we can send movement message when mouse is depressed # Do this only if it is our turn move_coord = self.hovered_tile.getPythonTag('pos') if self.parent.local_engine.units[self.parent.sel_unit_id][ 'move_dict'].has_key(move_coord): self.unit_move_destination = move_coord self.showMoveCompass(self.unit_move_destination) def mouseLeftClickUp(self): """Handles left mouse click actions when mouse button is depressed. Used for unit movement. """ o = None if self.hovered_compass_tile != None: x = self.turn_node.getPythonTag('pos')[0] y = self.turn_node.getPythonTag('pos')[1] orientation = int(self.hovered_compass_tile.getTag('key')) if orientation == utils.HEADING_NW: o = Point2(x - 1, y + 1) elif orientation == utils.HEADING_N: o = Point2(x, y + 1) elif orientation == utils.HEADING_NE: o = Point2(x + 1, y + 1) elif orientation == utils.HEADING_W: o = Point2(x - 1, y) elif orientation == utils.HEADING_E: o = Point2(x + 1, y) elif orientation == utils.HEADING_SW: o = Point2(x - 1, y - 1) elif orientation == utils.HEADING_S: o = Point2(x, y - 1) elif orientation == utils.HEADING_SE: o = Point2(x + 1, y - 1) else: o = None self.hideMoveCompass() if o != None: ClientMsg.move(self.parent.sel_unit_id, (x, y), (o.x, o.y)) def positionTask(self, task): # If turn node is displayed, you have to cancel turning or turn to be able to pick another unit or another tile to move to if self.turn_node.getTag('show') == '1': for tile in self.turn_np_list: pos = Point3( utils.TILE_SIZE * (tile.getPythonTag('pos')[0] + 0.5), utils.TILE_SIZE * (tile.getPythonTag('pos')[1]) + 0.5, utils.GROUND_LEVEL) pos2d = utils.pointCoordIn2d(pos) tile.setPos(pos2d) else: for unit in self.parent.render_manager.unit_renderer_dict.itervalues( ): p = utils.nodeCoordIn2d(unit.model) unit.node_2d.setPos(p) for tile in self.move_np_list: pos = Point3( utils.TILE_SIZE * (tile.getPythonTag('pos')[0] + 0.5), utils.TILE_SIZE * (tile.getPythonTag('pos')[1] + 0.5), utils.GROUND_LEVEL) pos2d = utils.pointCoordIn2d(pos) tile.setPos(pos2d) return task.cont def pickerTask(self, task): if self.parent._anim_in_process: self.hovered_unit_id = None self.hovered_tile = None self.hovered_compass_tile = None return task.cont if self.parent.interface.hovered_gui != None: if self.hovered_unit_id != None: self.parent.render_manager.unit_marker_renderer.unmarkHovered( self.hovered_unit_id) self.hovered_unit_id = None if self.hovered_tile != None and not self.hovered_tile.isEmpty(): self.hovered_tile.setColor(1, 1, 1) self.hovered_tile.setScale(0.05) self.color_scale_parallel.pause() if self.hovered_compass_tile != None and not self.hovered_compass_tile.isEmpty( ): self.hovered_compass_tile.setColor(1, 1, 1) self.hovered_compass_tile.setScale(0.05) self.color_scale_parallel.pause() return task.cont min_distance = 0.5 min_unit_id = None min_tile = None min_compass_tile = None if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() r2d = Point3(mpos.getX(), 0, mpos.getY()) a2d = aspect2d.getRelativePoint(render2d, r2d) self.mouse_node.setPos(a2d) # At the end of all this we have: # - min_distance to a unit or a movement node, IF this distance is lower than 0.5 which is set at the beginning # - min_unit_id - ID of unit which is closest to the mouse, or None if there is a movement tile closer, or if everything is further than 0.5 # - min_tile - nodepath of the movement tile closest to the mouse, or None if there is a unit closer, or if evertythin is further than 0.5 if self.turn_node.getTag('show') == '1': # Get 2d coordinates for every compass node for tile in self.turn_np_list: # We cannot do nodepath.getDistance() because tiles are reparented to self.turn_node and are in different coord space than mouse node # So we do simple vector math to get distance d = Vec3(self.mouse_node.getPos() - tile.getPos()).length() if d < min_distance: min_distance = d min_unit_id = None min_tile = None min_compass_tile = tile else: # Get 2d coordinates of all units for unit_id in self.parent.render_manager.unit_renderer_dict: unit = self.parent.render_manager.unit_renderer_dict[ unit_id] if self.parent.local_engine.isThisMyUnit(unit_id): # Calculate distance between every friendly unit and mouse cursor and remember closest unit d = self.mouse_node.getDistance(unit.node_2d) if d < min_distance: min_distance = d min_unit_id = unit_id else: # Calculate distance between every enemy unit and mouse cursor and remember closest unit d = self.mouse_node.getDistance(unit.node_2d) # To target enemy unit, distance has to be even smaller than needed for regular selection/movement if d < min_distance and d < 0.1: min_distance = d min_unit_id = unit_id # Get 2d coordinates for every movement node of the selected unit for tile in self.move_np_list: # We cannot do nodepath.getDistance() because tiles are reparented to self.move_node and are in different coord space than mouse node # So we do simple vector math to get distance d = Vec3(self.mouse_node.getPos() - tile.getPos()).length() if d < min_distance: min_distance = d min_unit_id = None min_tile = tile # If a unit is the closest to the mouse: # - hide movement nodes (Incubation style!) # - unmark last hovered unit # - unmark last hovered tile # - mark new hovered unit # TODO: ogs: potencijalna optimizacija da se provjeri da li je self.hovered_unit_id = min_unit_id, tada ne treba unmark+mark if min_compass_tile != None: if self.hovered_tile != None and not self.hovered_tile.isEmpty(): self.hovered_tile.setColor(1, 1, 1) self.hovered_tile.setScale(0.05) self.color_scale_parallel.pause() self.hovered_tile = None if min_compass_tile != self.hovered_compass_tile: if self.hovered_compass_tile != None and not self.hovered_compass_tile.isEmpty( ): self.hovered_compass_tile.setColor(1, 1, 1) self.hovered_compass_tile.setScale(0.05) self.color_scale_parallel.pause() min_compass_tile.setColor(1, 0, 0) s1 = Sequence( LerpColorInterval(min_compass_tile, 0.5, (1, 1, 0, 1)), LerpColorInterval(min_compass_tile, 0.5, (1, 0, 0, 1))) s2 = Sequence(LerpScaleInterval(min_compass_tile, 0.5, (0.1)), LerpScaleInterval(min_compass_tile, 0.5, (0.05))) self.color_scale_parallel = Parallel(s1, s2) self.color_scale_parallel.loop() self.hovered_compass_tile = min_compass_tile elif min_unit_id != None: self.move_node.detachNode() if min_unit_id != self.hovered_unit_id and self.hovered_unit_id != None: if self.parent.render_manager.unit_renderer_dict.has_key( int(self.hovered_unit_id)): self.parent.render_manager.unit_marker_renderer.unmarkHovered( self.hovered_unit_id) self.parent.render_manager.unit_marker_renderer.markHovered( min_unit_id) if self.hovered_tile != None and not self.hovered_tile.isEmpty(): self.hovered_tile.setColor(1, 1, 1) self.hovered_tile.setScale(0.05) self.color_scale_parallel.pause() self.hovered_tile = None self.hovered_unit_id = min_unit_id # If a movement tile is closest to the mouse: # - unmark last hovered unit # - unmark last marked tile # - show movement nodes (Incubation style!) # - mark new hovered tile elif min_tile != None: if self.hovered_unit_id != None: if self.parent.render_manager.unit_renderer_dict.has_key( int(self.hovered_unit_id)): self.parent.render_manager.unit_marker_renderer.unmarkHovered( self.hovered_unit_id) self.hovered_unit_id = None if min_tile != self.hovered_tile: self.move_node.reparentTo(aspect2d) if self.hovered_tile != None and not self.hovered_tile.isEmpty( ): self.hovered_tile.setColor(1, 1, 1) self.hovered_tile.setScale(0.05) self.color_scale_parallel.pause() min_tile.setColor(1, 0, 0) s1 = Sequence(LerpColorInterval(min_tile, 0.5, (1, 1, 0, 1)), LerpColorInterval(min_tile, 0.5, (1, 0, 0, 1))) s2 = Sequence(LerpScaleInterval(min_tile, 0.5, (0.1)), LerpScaleInterval(min_tile, 0.5, (0.05))) self.color_scale_parallel = Parallel(s1, s2) self.color_scale_parallel.loop() self.hovered_tile = min_tile # If neither any of the units nor any of the movement tiles is closer than 0.5: # - unmark last hovered unit # - unmark last hovered tile else: if self.hovered_unit_id != None: if self.parent.render_manager.unit_renderer_dict.has_key( int(self.hovered_unit_id)): self.parent.render_manager.unit_marker_renderer.unmarkHovered( self.hovered_unit_id) self.hovered_unit_id = None if self.hovered_tile != None and not self.hovered_tile.isEmpty(): self.hovered_tile.setColor(1, 1, 1) self.hovered_tile.setScale(0.05) self.color_scale_parallel.pause() self.hovered_tile = None if self.hovered_compass_tile != None and not self.hovered_compass_tile.isEmpty( ): self.hovered_compass_tile.setColor(1, 1, 1) self.hovered_compass_tile.setScale(0.05) self.color_scale_parallel.pause() self.hovered_compass_tile = None return task.cont
class Cuboid(object): def __init__(self, size, translation, rotation, color, text): self._visible = False wy, wx, wz = size[0], size[1], size[2] format = GeomVertexFormat.getV3c4() vdata = GeomVertexData('cu_points', format, Geom.UHStatic) vdata.setNumRows(8) self._pos_writer = GeomVertexWriter(vdata, 'vertex') self._color_writer = GeomVertexWriter(vdata, 'color') self._pos_writer.set_row(0) self._color_writer.set_row(0) self._pos_writer.addData3f(-0.5 * wx, -0.5 * wy, 0.) self._pos_writer.addData3f(-0.5 * wx, -0.5 * wy, wz) self._pos_writer.addData3f(0.5 * wx, -0.5 * wy, wz) self._pos_writer.addData3f(0.5 * wx, -0.5 * wy, 0.) self._pos_writer.addData3f(-0.5 * wx, 0.5 * wy, 0.) self._pos_writer.addData3f(-0.5 * wx, 0.5 * wy, wz) self._pos_writer.addData3f(0.5 * wx, 0.5 * wy, wz) self._pos_writer.addData3f(0.5 * wx, 0.5 * wy, 0.) for i in range(8): self._color_writer.addData4f(color[0], color[1], color[2], color[3]) lines = GeomLines(Geom.UHStatic) lines.addVertices(0, 1) lines.addVertices(1, 2) lines.addVertices(2, 3) lines.addVertices(3, 0) lines.addVertices(4, 5) lines.addVertices(5, 6) lines.addVertices(6, 7) lines.addVertices(7, 4) lines.addVertices(0, 4) lines.addVertices(1, 5) lines.addVertices(2, 6) lines.addVertices(3, 7) cuboid = Geom(vdata) cuboid.addPrimitive(lines) node = GeomNode('cuboid') node.addGeom(cuboid) self._node_path = NodePath(node) # self.title = OnscreenText(text=text, style=1, fg=(1, 1, 1, 1), pos=(-0.1, 0.1), scale=.05, # parent=self._node_path, align=TextNode.ARight) self._txt_node = TextNode('id') self._txt_node.setText(text) self._txt_node.setTextScale(0.2) self._txt_node.setCardColor(0, 0, 1, 1) self._txt_node.setCardAsMargin(0, 0, 0, 0) self._txt_node.setCardDecal(True) self._txt_node.set_align(2) text_geom = GeomNode('text') text_geom.addChild(self._txt_node) self._txt_np = NodePath(text_geom) self._txt_np.reparentTo(self._node_path) self.show() self.update_values(size, translation, rotation, color, text) def update_values(self, size, translation, rotation, color, text): if self._visible: self.update_bb(self._node_path, self._pos_writer, self._color_writer, tuple(size), tuple(translation), tuple(rotation), tuple(color), text, self._txt_node, self._txt_np) def hide(self): if self._visible: self._node_path.detachNode() self._visible = False def show(self): if not self._visible: self._node_path.reparentTo(base.render) self._node_path.setTwoSided(True) self._node_path.setTransparency(TransparencyAttrib.MAlpha) self._visible = True def update_bb(self, cuboid, pos_writer, color_writer, size, translation, rotation, color, text, text_node, text_np): wx, wy, wz = size pos_writer.setRow(0) color_writer.setRow(0) pos_writer.setData3f(-0.5 * wx, -0.5 * wy, 0.) pos_writer.setData3f(-0.5 * wx, -0.5 * wy, wz) pos_writer.setData3f(0.5 * wx, -0.5 * wy, wz) pos_writer.setData3f(0.5 * wx, -0.5 * wy, 0.) pos_writer.setData3f(-0.5 * wx, 0.5 * wy, 0.) pos_writer.setData3f(-0.5 * wx, 0.5 * wy, wz) pos_writer.setData3f(0.5 * wx, 0.5 * wy, wz) pos_writer.setData3f(0.5 * wx, 0.5 * wy, 0.) r, g, b, a = color for i in range(8): color_writer.setData4f(r, g, b, a) tx, ty, tz = translation ty = -ty rx, ry, rz = rotation rz = -rz cuboid.setPos(ty, tx, tz) cuboid.setHpr(-rz - 90., ry, rx) text_node.setText(text) text_np.setPos((0., 0., wz + 0.2)) text_np.setHpr(rz + 90., 0, 0)