class StimulusBase(ShowBase): """Base class from which all stimuli inherit. Defines the global timing loop.""" def __init__(self, shared): loadPrcFileData("", """load-display pandagl sync-video #t fullscreen #f win-origin 0 0 undecorated #t cursor-hidden #t win-size 7680 1080 show-frame-rate-meter #t auto-single-cpu-affinity #f """) TrueClock.getGlobalPtr().setCpuAffinity(0xFFFFFFFF) self.shared = shared ShowBase.__init__(self) self.global_time = 0.0 self.statustex1 = create_color_texture([0, 0, 0]) self.statustex2 = create_color_texture([255, 255, 255]) self.statusimage1 = OnscreenImage(self.statustex1, scale=(0.015, 0.015, 0.015), sort=20, pos=(self.getAspectRatio() - 0.01, 0, -1 + 0.01)) self.taskMgr.add(self.loop, "Primary loop") # Calibration details: self.calibrated_length = 4 * 56.9 def loop(self, task): self.global_time += globalClock.getDt() # Run actual stimulus: self.update_stimulus(task.frame, self.global_time) # Flip flicker test: self.update_status(task.frame) if self.shared.running.value == 1: return task.cont else: self.destroy() sys.exit() return task.done def update_status(self, frame_number): if frame_number % 2 == 0: self.statusimage1.setTexture(self.statustex1) else: self.statusimage1.setTexture(self.statustex2) def update_stimulus(self, frame_number, time): pass
class ScreenDecorationManager: def __init__(self): self.tex_judgements = {} for i in ["PERFECT","GOOD","OK","BAD","MISS"]: self.tex_judgements[i] = loader.loadTexture("image/j_%s.png" % i.lower()) ## Judgement message self.image_judgement = OnscreenImage(image=self.tex_judgements["OK"],pos=(0, 0, 0), scale=(256.0/base.win.getXSize(),1,32.0/base.win.getYSize()), parent=render2d) self.image_judgement.setTransparency(TransparencyAttrib.MAlpha) #self.image_judgement.setPos(-0.7, 1, 0.6) self.image_judgement.setAlphaScale(0) interval_pos = LerpPosInterval(self.image_judgement, duration=0.1, startPos=VBase3(-1.2, 1, 0.5), pos=VBase3(-0.7, 1, 0.5), blendType='easeOut') interval_alpha = LerpFunc(self.image_judgement.setAlphaScale, duration=0.1, blendType='easeOut') interval_fade = LerpFunc(self.image_judgement.setAlphaScale, fromData=1, toData=0, duration=1.0, blendType='easeOut') self.judgement_enters = Sequence(Parallel(interval_pos, interval_alpha), Wait(1.0), interval_fade) ## Chain message text_node = TextNode('chain_msg') text_node.setAlign(TextNode.ACenter) text_node.setFont(babelfish_font) text_node.setTextColor(1, 1, 0.16, .9) text_node.setShadow(0.05, 0.05) text_node.setShadowColor(0.05, 0, 0.43, .9) self.chain_msg = aspect2d.attachNewNode(text_node) self.chain_msg.setPos(-.9, 1, 0.35) self.chain_msg.setScale(0.11) def judgement_msg(self, msg, chain): if self.judgement_enters.isPlaying(): self.judgement_enters.clearToInitial() self.image_judgement.setTexture(self.tex_judgements[msg]) self.judgement_enters.start() if chain > 1: self.chain_msg.node().setText("%d CHAIN" % chain) taskMgr.add(self.task_ClearJudgementTask, "clear-judgement") def task_ClearJudgementTask(self, task): if task.time < 1.5: return Task.cont self.chain_msg.node().clearText() def __del__(self): self.judgement_enters.finish() self.image_judgement.destroy() self.chain_msg.removeNode()
def set_ranking(self): items = game.logic.season.logic.ranking.logic.ranking.items() sorted_ranking = reversed(sorted(items, key=lambda el: el[1])) txt = OnscreenText(text=_('Ranking'), scale=.1, pos=(0, .3), font=self.font, fg=self.text_bg) self.widgets += [txt] for i, car in enumerate(sorted_ranking): idx, name, _car, skills = next(driver for driver in self.props.drivers if driver[3] == car[0]) is_car = car[0] == self.props.car_path txt = OnscreenText(text=str(car[1]) + ' ' + name, align=TextNode.A_left, scale=.072, pos=(-.2, .1 - i * .16), font=self.font, fg=self.text_fg if is_car else self.text_bg) self.widgets += [txt] img = OnscreenImage(self.props.cars_path % car[0], pos=(-.36, 1, .12 - i * .16), scale=.074) self.widgets += [img] with open(eng.curr_path + 'yyagl/assets/shaders/filter.vert') as ffilter: vert = ffilter.read() with open(eng.curr_path + 'yyagl/assets/shaders/drv_car.frag') as ffilter: frag = ffilter.read() shader = Shader.make(Shader.SL_GLSL, vert, frag) img.setShader(shader) img.setTransparency(True) ts = TextureStage('ts') ts.setMode(TextureStage.MDecal) txt_path = self.props.drivers_path % idx img.setTexture(ts, loader.loadTexture(txt_path))
def set_grid(self): txt = OnscreenText(text=_('Starting grid'), scale=.1, pos=(-1.0, .3), font=self.font, fg=self.text_bg) self.widgets += [txt] for i, car in enumerate(self.props.grid): idx, name, _car, skills = next(driver for driver in self.props.drivers if driver[3] == car) is_car = car == self.props.car_path txt = OnscreenText(text=str(i + 1) + '. ' + name, align=TextNode.A_left, scale=.072, pos=(-1.28, .1 - i * .16), font=self.font, fg=self.text_fg if is_car else self.text_bg) self.widgets += [txt] img = OnscreenImage(self.props.cars_path % car, pos=(-1.42, 1, .12 - i * .16), scale=.074) self.widgets += [img] with open(eng.curr_path + 'yyagl/assets/shaders/filter.vert') as ffilter: vert = ffilter.read() with open(eng.curr_path + 'yyagl/assets/shaders/drv_car.frag') as f: frag = f.read() shader = Shader.make(Shader.SL_GLSL, vert, frag) img.setShader(shader) img.setTransparency(True) ts = TextureStage('ts') ts.setMode(TextureStage.MDecal) txt_path = self.props.drivers_path % idx img.setTexture(ts, loader.loadTexture(txt_path))
def show(self, race_ranking, lap_times, drivers, player_car_name): track = self.props.track_path self.result_frm = DirectFrame(frameColor=(.8, .8, .8, .64), frameSize=(-2, 2, -1, 1)) laps = len(lap_times) text_bg = self.props.menu_args.text_bg pars = {'scale': .1, 'fg': text_bg, 'font': self.props.menu_args.font} # ref into race self.__res_txts = [ OnscreenText(str(round(lap_times[i], 2)), pos=(0, .47 - .2 * (i + 1)), **pars) for i in range(laps) ] self.__res_txts += [OnscreenText(_('LAP'), pos=(-.6, .6), **pars)] self.__res_txts += [OnscreenText(_('TIME'), pos=(0, .6), **pars)] self.__res_txts += [ OnscreenText(_('RANKING'), pos=(.5, .6), align=TextNode.A_left, **pars) ] self.__res_txts += [ OnscreenText(str(i), pos=(-.6, .47 - .2 * i), **pars) for i in range(1, 4) ] race_ranking_sorted = sorted(race_ranking.items(), key=lambda x: x[1]) race_ranking_sorted = reversed([el[0] for el in race_ranking_sorted]) for i, car in enumerate(race_ranking_sorted): carinfo = next(drv for drv in drivers if drv[3] == car) idx, name, skills, _car = carinfo is_car = car == player_car_name fgc = self.props.menu_args.text_fg if is_car else text_bg txt = OnscreenText(text=str(i + 1) + '. ' + name, align=TextNode.A_left, scale=.072, pos=(.68, .44 - .16 * (i + 1)), font=self.props.menu_args.font, fg=fgc) img = OnscreenImage(self.props.cars_imgs % car, pos=(.58, 1, .47 - (i + 1) * .16), scale=.074) with open(eng.curr_path + 'yyagl/assets/shaders/filter.vert') as f: vert = f.read() with open(eng.curr_path + 'yyagl/assets/shaders/drv_car.frag') as f: frag = f.read() shader = Shader.make(Shader.SL_GLSL, vert, frag) img.setShader(shader) img.setTransparency(True) ts = TextureStage('ts') ts.setMode(TextureStage.MDecal) txt_path = self.props.drivers_imgs % idx img.setTexture(ts, loader.loadTexture(txt_path)) self.__res_txts += [txt, img] self.__res_txts += [ OnscreenText(_('share:'), pos=(-.1, -.82), align=TextNode.A_right, **pars) ] self.__buttons = [] curr_time = min(game.player_car.logic.lap_times or [0]) facebook_url = self.props.share_urls[0] #TODO: find a way to share the time on Facebook twitter_url = self.props.share_urls[1] twitter_url = twitter_url.format(time=round(curr_time, 2), track=track) plus_url = self.props.share_urls[2] #TODO: find a way to share the time on Google Plus tumblr_url = self.props.share_urls[3] #TODO: find a way to share the time on Tumblr sites = [('facebook', facebook_url), ('twitter', twitter_url), ('google_plus', plus_url), ('tumblr', tumblr_url)] self.__buttons += [ ImageButton(scale=.078, pos=(.02 + i * .18, 1, -.79), frameColor=(0, 0, 0, 0), image=self.props.share_imgs % site[0], command=eng.open_browser, extraArgs=[site[1]], rolloverSound=self.props.menu_args.rollover, clickSound=self.props.menu_args.click) for i, site in enumerate(sites) ] def step(): self.notify('on_race_step', race_ranking) self.destroy() Subject.destroy(self) cont_btn = DirectButton(text=_('Continue'), pos=(0, 1, -.6), command=step, **self.props.menu_args.btn_args) self.__buttons += [cont_btn]
class ScreenDecorationManager: def __init__(self): self.tex_judgements = {} for i in ["PERFECT", "GOOD", "OK", "BAD", "MISS"]: self.tex_judgements[i] = loader.loadTexture("image/j_%s.png" % i.lower()) ## Judgement message self.image_judgement = OnscreenImage( image=self.tex_judgements["OK"], pos=(0, 0, 0), scale=(256.0 / base.win.getXSize(), 1, 32.0 / base.win.getYSize()), parent=render2d) self.image_judgement.setTransparency(TransparencyAttrib.MAlpha) #self.image_judgement.setPos(-0.7, 1, 0.6) self.image_judgement.setAlphaScale(0) interval_pos = LerpPosInterval(self.image_judgement, duration=0.1, startPos=VBase3(-1.2, 1, 0.5), pos=VBase3(-0.7, 1, 0.5), blendType='easeOut') interval_alpha = LerpFunc(self.image_judgement.setAlphaScale, duration=0.1, blendType='easeOut') interval_fade = LerpFunc(self.image_judgement.setAlphaScale, fromData=1, toData=0, duration=1.0, blendType='easeOut') self.judgement_enters = Sequence( Parallel(interval_pos, interval_alpha), Wait(1.0), interval_fade) ## Chain message text_node = TextNode('chain_msg') text_node.setAlign(TextNode.ACenter) text_node.setFont(babelfish_font) text_node.setTextColor(1, 1, 0.16, .9) text_node.setShadow(0.05, 0.05) text_node.setShadowColor(0.05, 0, 0.43, .9) self.chain_msg = aspect2d.attachNewNode(text_node) self.chain_msg.setPos(-.9, 1, 0.35) self.chain_msg.setScale(0.11) def judgement_msg(self, msg, chain): if self.judgement_enters.isPlaying(): self.judgement_enters.clearToInitial() self.image_judgement.setTexture(self.tex_judgements[msg]) self.judgement_enters.start() if chain > 1: self.chain_msg.node().setText("%d CHAIN" % chain) taskMgr.add(self.task_ClearJudgementTask, "clear-judgement") def task_ClearJudgementTask(self, task): if task.time < 1.5: return Task.cont self.chain_msg.node().clearText() def __del__(self): self.judgement_enters.finish() self.image_judgement.destroy() self.chain_msg.removeNode()
class DriverPageGui(ThanksPageGui): def __init__(self, mdt, menu_args, driverpage_props): self.props = driverpage_props ThanksPageGui.__init__(self, mdt, menu_args) def bld_page(self): self.skills = [drv[2] for drv in self.props.drivers] menu_gui = self.mdt.menu.gui menu_args = self.mdt.menu.gui.menu_args widgets = [ OnscreenText(text=_('Select the driver'), pos=(0, .8), **menu_gui.menu_args.text_args) ] self.track_path = self.mdt.menu.track t_a = self.mdt.menu.gui.menu_args.text_args.copy() del t_a['scale'] name = OnscreenText(_('Write your name:'), pos=(-.1, .6), scale=.06, align=TextNode.A_right, **t_a) self.ent = DirectEntry(scale=.08, pos=(0, 1, .6), entryFont=menu_args.font, width=12, frameColor=menu_args.btn_color, initialText=self.props.player_name or _('your name')) self.ent.onscreenText['fg'] = menu_args.text_fg self.drivers = [] for row, col in product(range(2), range(4)): idx = (col + 1) + row * 4 widgets += [ ImgBtn(scale=.24, pos=(-.75 + col * .5, 1, .25 - row * .5), frameColor=(0, 0, 0, 0), image=self.props.drivers_img[0] % idx, command=self.on_click, extraArgs=[idx], **self.mdt.menu.gui.menu_args.imgbtn_args) ] self.drivers += [widgets[-1]] sign = lambda x: '\1green\1+\2' if x > 0 else '' psign = lambda x: '+' if x == 0 else sign(x) def ppcol(x): return '\1green\1%s\2' % x if x > 0 else '\1red\1%s\2' % x pcol = lambda x: x if x == 0 else ppcol(x) def add_lab(txt, pos_z): return OnscreenText(txt + ':', pos=(-.95 + col * .5, pos_z - row * .5), scale=.046, align=TextNode.A_left, **t_a) def add_txt(val, pos_z): return OnscreenText('%s%s%%' % (psign(val), pcol(val)), pos=(-.55 + col * .5, pos_z - row * .5), scale=.052, align=TextNode.A_right, **t_a) lab_lst = [(_('adherence'), .04), (_('speed'), .16), (_('stability'), .1)] widgets += map(lambda lab_def: add_lab(*lab_def), lab_lst) txt_lst = [(self.skills[idx - 1][1], .04), (self.skills[idx - 1][0], .16), (self.skills[idx - 1][2], .1)] widgets += map(lambda txt_def: add_txt(*txt_def), txt_lst) self.img = OnscreenImage(self.props.cars_img % self.mdt.car, parent=base.a2dBottomRight, pos=(-.38, 1, .38), scale=.32) widgets += [self.img, name, self.ent] map(self.add_widget, widgets) fpath = eng.curr_path + 'yyagl/assets/shaders/filter.vert' with open(fpath) as ffilter: vert = ffilter.read() shader = Shader.make(Shader.SL_GLSL, vert, frag) self.img.setShader(shader) self.img.setTransparency(True) self.t_s = TextureStage('ts') self.t_s.setMode(TextureStage.MDecal) empty_img = PNMImage(1, 1) empty_img.add_alpha() empty_img.alpha_fill(0) tex = Texture() tex.load(empty_img) self.img.setTexture(self.t_s, tex) ThanksPageGui.bld_page(self) self.update_tsk = taskMgr.add(self.update_text, 'update text') self.enable_buttons(False) def enable_buttons(self, enable): for drv in self.drivers: drv['state'] = NORMAL if enable else DISABLED drv.setShaderInput('enable', 1 if enable else .2) # do wdg.enable, wdg.disable def update_text(self, task): has_name = self.ent.get() != _('your name') if has_name and self.ent.get().startswith(_('your name')): self.ent.enterText(self.ent.get()[len(_('your name')):]) self.enable_buttons(True) elif self.ent.get() in [_('your name')[:-1], '']: self.ent.enterText('') self.enable_buttons(False) elif self.ent.get() not in [_('your name'), '']: self.enable_buttons(True) return task.cont # don't do a task, attach to modifications events def on_click(self, i): txt_path = self.props.drivers_img[1] self.img.setTexture(self.t_s, loader.loadTexture(txt_path % i)) self.widgets[-1]['state'] = DISABLED self.enable_buttons(False) taskMgr.remove(self.update_tsk) names = Utils().get_thanks(6) cars = self.props.cars[:] cars.remove(self.mdt.car) shuffle(cars) drv_idx = range(1, 9) drv_idx.remove(i) shuffle(drv_idx) drivers = [(i, self.ent.get(), self.skills[i - 1], self.mdt.car)] drivers += [(drv_idx[j], names[j], self.skills[j - 1], cars[j]) for j in range(6)] self.mdt.menu.gui.notify('on_driver_selected', self.ent.get(), drivers, self.mdt.track, self.mdt.car) def destroy(self): self.img = None taskMgr.remove(self.update_tsk) PageGui.destroy(self)
class Game(ShowBase): def game(self): success, img = self.cap.read() # Find keypoints kp, des = self.features.extract(img) # Match keypoints matches = self.features.match(des, self.card.des) # uncomment for drawing keypoints # img = self.features.draw(matches, img, self.card.img, kp, self.card.kp) if len(matches) > self.features.MINMATCHES: # Homography & projection matrix H = self.geometry.computeHomography(kp, self.card.kp, matches) frame = self.geometry.drawRect(img, self.card.img, 2, (20, 20, 20), H) self.projection, self.translation = self.geometry.calcProjection(H) if success: # Create texture from openCV image # https://discourse.panda3d.org/t/opencv-image-as-a-panda-texture-clarification/12480/3 shape = img.shape # (720, 1280, 3) self.img = cv2.flip(img, 0) self.tex = Texture("detect") self.tex.setup2dTexture(shape[1], shape[0], Texture.TUnsignedByte, Texture.FRgb) p = PTAUchar.emptyArray(0) p.setData(self.img) self.tex.setRamImage(CPTAUchar(p)) def __init__(self): ShowBase.__init__(self) # initialise cv2 camera self.cap = cv2.VideoCapture(0) # (1) for external webcam # self.cap = cv2.VideoCapture(1) # Initialise game classes self.features = FeatureClass(min_matches=20, max_matches=75) self.geometry = GeometryClass() self.card = Card('card_1', 50, self.features) ch = cv2.waitKey(1) & 0xFF if ch == ord('1'): self.mode = 1 # Start image processing self.game() # Render webcam texture to background self.test = OnscreenImage(parent=self.render2d, image=self.tex, scale=1.0, pos=(0, 0, 0)) self.cam.node().getDisplayRegion(0).setSort(20) # Set directional light dlight = DirectionalLight('my dlight') dlnp = self.render.attachNewNode(dlight) # Load model self.model = Actor("models/panda-model", {"walk": "models/panda-walk4"}) # Scale and flip model on Y self.model.setScale(0.03, -0.03, 0.03) self.model.setAttrib(CullFaceAttrib.makeReverse()) self.model.setPos(0, 25, 0) # Reparent the model to render. self.model.reparentTo(self.render) # Animate model self.model.loop("walk") # Apply directional light to model self.model.setLight(dlnp) self.accept('escape', sys.exit) self.taskMgr.add(self.loop, "loop") def loop(self, task): self.game() self.test.setTexture(self.tex) # Apply rotation and displacement to the model x = -self.translation[0] / 10 # + self.offset[0]/10 y = -self.translation[2] / 10 z = self.translation[1] / 10 # - self.offset[1]/10 self.model.setPos(x, y, z) angles = self.rotationMatrixToEulerAngles(self.projection[:3]) z = angles[2] + 180 x = angles[1] y = -angles[0] + 90 self.model.setHpr(x, y, z) return task.cont def rotationMatrixToEulerAngles(self, R): # Calculate euler angles from projection matrix sy = math.sqrt(R[0, 0] * R[0, 0] + R[1, 0] * R[1, 0]) singular = sy < 1e-6 if not singular: x = math.atan2(R[2, 1], R[2, 2]) y = math.atan2(-R[2, 0], sy) z = math.atan2(R[1, 0], R[0, 0]) else: x = math.atan2(-R[1, 2], R[1, 1]) y = math.atan2(-R[2, 0], sy) z = 0 return np.array([np.degrees(x), np.degrees(y), np.degrees(z)])