class GameView(ScreenManager): def __init__ (self, app): super(GameView, self).__init__(transition=WipeTransition()) self.app = app self.graphics_widget = FloatLayout() image = Image(source = PATH + "splash.png", keep_ratio=False, allow_stretch=True,\ size=(SCREEN_WIDTH, SCREEN_HEIGHT), size_hint=(None, None), pos=(0,0)) self.graphics_widget.add_widget(image) screen = Screen(name="0") screen.add_widget(self.graphics_widget) self.add_widget(screen) self.current = "0" # self.load_sounds() self.load_textures() #self.load_sprites() self.load_gems() # self.schedules = [] self.image_hero = None # self.image_score = MyImage(source = PATH + "score_bg.png", allow_stretch=True) self.image_score.set_score(0) self.image_score.set_shadow(False) self.image_score.set_font_size(30) self.image_score.set_label_position(3,4) self.image_score.size_hint = (.2, .2) self.image_score.pos_hint = {'x':.8, 'y':.8} # self.button_reset = MyButton(source=PATH + "restart.png", on_press=self.reset, opacity=0.5,\ background_color = (0,0,0,0), size = (X_BLOCK, Y_BLOCK), border=(0,0,0,0)) self.button_reset.size_hint = (.1, .1) self.button_reset.pos_hint = {'x': 0, 'y':.9} self.progress_bar = ProgressBar(max=500, opacity=0) #CURRENTLY HIDDEN with self.progress_bar.canvas: Color(0,0,0,0) self.progress_bar.size_hint = (.6, .05) self.progress_bar.pos_hint = {'x': 0.2, 'y': 0} self.progress_bar.value = 0 self.schedule(self.reset_level, 3) def unschedule_all(self): for s in self.schedules: Clock.unschedule(s) self.schedules = [] def unschedule_single(self, dt=None): self.schedules = self.schedules[1:] def schedule(self, func, delay): if func not in self.schedules: self.schedules.append(func) Clock.schedule_once(func, delay) Clock.schedule_once(self.unschedule_single, delay) def reset(self, widget=None): print "Reset" #save_state(1) #self.reset_level() self.level = 1 save_state(1) self.app.stop() def reset_level(self, dt=None): self.level = int(get_state()) try: Animation.cancel_all(self.scatter_hero) except: pass try: Animation.cancel_all(self.scatter_baddy) except: pass Animation.cancel_all(self.progress_bar) self.unschedule_all() self.setup_battle() def get_level_data(self): data = get_level_data(self.level) self.baddy_points_for_level = int(data[0]) self.weapons = [int(x) for x in data[1].split(",")] self.score_threshold = int(data[2]) self.maximum_attacks = int(data[3]) self.time_limit = int(data[4]) self.baddy_image = data[5] self.baddy_ratio_for_level = int(data[6]) self.baddy_label_deltax = int(data[7]) self.baddy_label_deltay = int(data[8]) self.level_potions = [int(x) for x in data[9].split(",") if x] self.textures_data = data[10].split(";") #self.sprites_data = data[11].split(";") #if self.sprites_data == ['']: # self.sprites_data = [] def setup_battle(self, dt=None): self.graphics_widget.remove_widget(self.button_reset) self.graphics_widget.remove_widget(self.image_score) self.graphics_widget.remove_widget(self.progress_bar) if self.level == 11: graphics_widget = FloatLayout() image = Image(source = PATH + "end.png", keep_ratio=False, allow_stretch=True,\ size=(SCREEN_WIDTH, SCREEN_HEIGHT), size_hint=(None, None), pos=(0,0)) graphics_widget.add_widget(image) graphics_widget.add_widget(self.button_reset) screen = Screen(name="end") screen.add_widget(graphics_widget) self.add_widget(screen) self.current=screen.name else: self.get_level_data() graphics_widget = self.set_background() screen = Screen(name=str(self.level)) screen.add_widget(graphics_widget) self.graphics_widget = graphics_widget self.add_widget(screen) self.current=screen.name if self.score_threshold > 0: self.level_score = - self.score_threshold else: self.level_score = 0 self.image_score.set_score(self.level_score) if self.level < 3: self.start_battle() else: self.schedule(self.start_battle, 0) #WAS 2 self.graphics_widget.add_widget(self.button_reset) self.graphics_widget.add_widget(self.progress_bar) self.graphics_widget.add_widget(self.image_score) def repeat_battle(self, dt=None): self.image_hero = None self.level_score = 0 self.image_score.set_score(self.level_score) self.start_battle() def start_battle(self, dt=None): self.attacks_tried = 0 self._picked_gems = [] if self.level_potions: self.create_potions(self.level_potions) else: self.potion_buttons = [] self.create_gems(self.weapons) # min_wait = 0 #WAS 3 if self.level < 3: min_wait = 0 self.schedule(self.introduce_hero, min_wait) if self.level == 1: self.schedule(self.introduce_baddy, min_wait) else: self.schedule(self.introduce_baddy, min_wait + 2) self.schedule(self.talk_baddy, min_wait + 4) self.schedule(self.talk_hero, min_wait + 5.5) self.schedule(self.talk_baddy, min_wait + 6.5) if self.level == 1: self.schedule(self.show_gems, 0) else: self.schedule(self.show_gems, min_wait + 8) if self.score_threshold > 0: self.image_score.flash(10) self.schedule(self.show_potions, min_wait + 8) self.schedule(self.look_alive, min_wait + 8) self.schedule(self.handle_timed_battle, min_wait + 8) if self.level == 1: self.schedule(self.flash_gem, min_wait + 11) #self.schedule(self.flash_hero, min_wait + 15) def flash_gem(self, dt=None): for g in self.gems: if g: g.flash(10) def flash_hero(self, widget=None, event=None): self.image_hero.flash(10) def handle_timed_battle(self, dt=None): if self.time_limit > 0: anim1 = Animation(x = X_BLOCK, duration=self.time_limit) anim1.bind(on_complete = self.level_failed) anim1.start(self.scatter_baddy) self.progress_bar.value = self.progress_bar.max anim2 = Animation(value = 0, duration=self.time_limit) anim2.start(self.progress_bar) def create_gems(self, numbers): self.gems = [None] * 10 self.gem_values = [0] * 10 for i in range(len(numbers)): n = numbers[i] #gem = MyImage(keep_ratio=True, allow_stretch=False, color=(0,0,0,0), keep_data=True) #gem.set_shadow(False) #with gem.canvas: # gem.rectangle = Rectangle(texture=self.gem_sprites[n].texture, size = (X_BLOCK,Y_BLOCK)) gem = MyImage(source = self.gem_sources[n],keep_ratio=False, allow_stretch=True, keep_data=True) gem.set_shadow(False) self.gems[n] = gem self.gem_values[n] = n def drop_gem(self, widget=None, event=None): if widget not in self.graphics_widget.children: return True if widget.x > self.scatter_hero.x and widget.x < self.scatter_hero.x + self.image_hero.width * 2: if widget.y > self.scatter_hero.y and widget.y < self.scatter_hero.y + self.image_hero.height * 2: self.image_hero.stop_flash() self.handle_player_action(widget) return True else: self.hide_gems() self.show_gems() self.hide_potions() self.show_potions() else: self.hide_gems() self.show_gems() self.hide_potions() self.show_potions() return False def pick_gem(self, widget=None, event=None): self._picked_gems.append(widget) self.flash_hero() def hide_gems(self, dt=None, dummy=None): for scatter in self.gem_scatters: if scatter.children: scatter.remove_widget(scatter.children[-1]) self.graphics_widget.remove_widget(scatter) def show_gems(self, dt=None, dummy=None): self.gem_scatters = [] filler = (8 - len(self.weapons)) / 2.0 for i in range(len(self.weapons)): gem = self.gems[self.weapons[i]] scatter = Scatter(do_rotation=False, do_scale=False, color=(0,0,0,0), size_hint=(0.1,0.1)) scatter.add_widget(gem) gem.bind(on_touch_down=self.flash_hero) scatter.bind(on_touch_up=self.drop_gem) scatter.pos = ((filler + i) * X_BLOCK, 0) scatter.scale = 1 try: self.graphics_widget.add_widget(scatter) self.gem_scatters.append(scatter) except: pass def bring_to_front(self, widget): self.graphics_widget.remove_widget(widget) self.graphics_widget.add_widget(widget) def set_background(self): graphics_widget = FloatLayout() for td in self.textures_data: filename,xpos,ypos,width,height = td.split(":") xpos = float(xpos) ypos = float(ypos) image = MyImage(keep_ratio=True, allow_stretch=False, color=(0,0,0,0)) image.set_shadow(False) with image.canvas: Rectangle(texture=self.textures[filename].texture, size=(float(width) * X_BLOCK, float(height) * Y_BLOCK)) scatter = Scatter(do_rotation=False, do_scale=False, do_translation=False) scatter.pos = (xpos * X_BLOCK, ypos * Y_BLOCK) scatter.add_widget(image) graphics_widget.add_widget(scatter) #for td in self.sprites_data: # filename,xpos,ypos,width,height = td.split(":") # xpos = float(xpos) # ypos = float(ypos) # image = MyImage(texture = self.sprites[filename].texture, keep_ratio=True, allow_stretch=False) # image.set_shadow(False) # scatter = Scatter(do_rotation=False, do_scale=False, do_translation=False) # scatter.pos = (xpos * X_BLOCK, (ypos + 4) * Y_BLOCK / 2) # scatter.add_widget(image) # graphics_widget.add_widget(scatter) # scatter.scale = 6 - ypos * 1.5 return graphics_widget def introduce_hero(self, dt=None): self.image_hero = MyImage(source = PATH + "hero.png", keep_ratio=False, allow_stretch=True, keep_data=True) self.image_hero.set_label_position(-4, -12) self.image_hero.set_shadow(True) self.scatter_hero = Scatter(do_rotation=False, do_scale=False, do_translation=False) self.scatter_hero.add_widget(self.image_hero) self.scatter_hero.scale= 2 + (0.5 * SCREEN_DENSITY) if self.level < 3: self.hero_position = [X_BLOCK, Y_BLOCK] self.scatter_hero.pos = (self.hero_position[0], self.hero_position[1]) self.graphics_widget.add_widget(self.scatter_hero) else: self.schedule(self.sounds['hero_song'].play, 1.0) self.hero_position = [- 2 * X_BLOCK, Y_BLOCK] self.scatter_hero.pos = (self.hero_position[0], self.hero_position[1]) self.graphics_widget.add_widget(self.scatter_hero) # self.image_hero.walk(60, 2.4 * X_BLOCK) anim = Animation(x = X_BLOCK, duration=4) anim.start(self.scatter_hero) self.image_score.set_score(self.level_score) def introduce_baddy(self, dt=None): self.baddy_size_ratio = self.baddy_ratio_for_level self.baddy_points = self.baddy_points_for_level self.image_baddy = MyImage(source = PATH + self.baddy_image, keep_ratio=False, allow_stretch=True) self.image_baddy.set_label_position(self.baddy_label_deltax, self.baddy_label_deltay) self.image_baddy.set_score(self.baddy_points) self.scatter_baddy = Scatter(do_rotation=False, do_scale=False, do_translation=False) self.scatter_baddy.add_widget(self.image_baddy) self.baddy_size = [X_BLOCK, Y_BLOCK] self.baddy_step = (4 * X_BLOCK + 0.0) / self.maximum_attacks self.scatter_baddy.scale = self.baddy_size_ratio # * SCREEN_DENSITY self.scatter_baddy.pos = (8 * X_BLOCK, Y_BLOCK) self.graphics_widget.add_widget(self.scatter_baddy) self.image_baddy.walk(30, 60) anim = Animation(x=5 * X_BLOCK, duration=2) anim.start(self.scatter_baddy) self.baddy_position = [5 * X_BLOCK, Y_BLOCK] def create_potions(self, numbers): self.potion_buttons = [] self.potion_button_values = [] for n in numbers: button = MyButton(source=PATH + "potion.png",background_color=[0,0,0,0], label_text="-1", font_size = 30) self.potion_buttons.append(button) self.potion_button_values.append(n) button.pos_hint = {'x': .45,'y': .85} button.size_hint = (0.12, 0.12) button.bind(on_press=self.handle_potion) def show_potions(self, dt=None): for button in self.potion_buttons: self.graphics_widget.add_widget(button) def hide_potions(self): for button in self.potion_buttons: self.graphics_widget.remove_widget(button) def handle_potion(self, widget=None): value = self.potion_button_values[self.potion_buttons.index(widget)] self.image_baddy.flash(5) self.baddy_points = self.baddy_points + value self.image_baddy.set_score(self.baddy_points) self.graphics_widget.remove_widget(widget) self.potion_buttons.remove(widget) self.potion_button_values.remove(value) self.decide_next_stage() def handle_player_action(self, widget=None): # HANDLE MULTIPLE WIDGETS USING self._PICKED_GEMS AND THEN CLEAR IT! try: self.graphics_widget.remove_widget(widget) except: pass image = widget.children[-1] self.hide_gems() Clock.unschedule(self.image_hero.look_alive) Clock.unschedule(self.image_baddy.look_alive) # widget.pos = (X_BLOCK / (20.0 * (SCREEN_DENSITY **2) * SCREEN_RATIO ), Y_BLOCK / (16 * (SCREEN_DENSITY**2) * SCREEN_RATIO) ) # widget.scale = 0.3 widget.add_widget(image) self.current_gem = widget self.scatter_hero.add_widget(widget) self.image_hero.walk(40, 60) self.image_baddy.walk(40, 60) anim1 = Animation(x = 3 * X_BLOCK, t='out_quad') anim1.start(self.scatter_hero) anim2 = Animation(x = 3.1 * X_BLOCK, t='out_quad') anim2.start(self.scatter_baddy) self.attacks_tried = self.attacks_tried + 1 if self.maximum_attacks > 0: self.baddy_position[0] = self.baddy_position[0] - ((self.attacks_tried +0.0) / self.maximum_attacks) * self.baddy_step self.schedule(self.sounds['hero_charge'].play, 0.1) self.schedule(self.sounds['baddy_charge'].play, 0.5) #Handle hit hit_value = self.gems.index(widget.children[-1]) if self.baddy_points / (hit_value + 0.0) == self.baddy_points / hit_value: if self.baddy_size_ratio <= self.baddy_ratio_for_level: self.level_score = self.level_score + hit_value * self.baddy_points self.baddy_points = self.baddy_points / hit_value self.baddy_size_ratio = self.baddy_size_ratio - 1 if self.baddy_size_ratio == 0: self.baddy_size_ratio = 0.1 else: self.baddy_points = self.baddy_points * hit_value self.baddy_size_ratio = self.baddy_size_ratio + 1 anim1.bind(on_complete = self.update) def baddy_vanquished(self, widget=None, event=None): self.graphics_widget.remove_widget(self.progress_bar) Animation.cancel_all(self.progress_bar) Animation.cancel_all(self.scatter_baddy, 'x') self.celebrate() self.image_baddy.walk(20, 40) self.image_baddy.children[-1].text="" anim1 = Animation(size = (1,1)) anim1.start(self.image_baddy) self.hide_gems() if self.level_score < 0: print "NOTIFY USER ABOUT THRESHOLD!" self.image_score.flash(10) self.schedule(self.level_failed, 2) else: self.schedule(self.move_to_next_battle, 2) def level_failed(self, widget=None, event=None): self.graphics_widget.remove_widget(self.progress_bar) Animation.cancel_all(self.progress_bar) Animation.cancel_all(self.scatter_baddy, 'x') if self.baddy_points < 2 and self.level_score >= self.score_threshold: return self.hide_gems() anim = Animation(x = - 4 * X_BLOCK, duration = 2) self.image_hero.walk(10, 4 * X_BLOCK) anim.start(self.image_hero) self.image_baddy.celebrate(240,60) self.schedule(self.move_to_repeat_battle, 2) def move_to_repeat_battle(self, widget=None, event=None): self.graphics_widget.remove_widget(self.scatter_hero) anim = Animation(x = 8 * X_BLOCK, duration = 12) self.image_baddy.walk(30, 8 * X_BLOCK) anim.start(self.image_baddy) self.schedule(self.repeat_battle, 3) def move_to_next_battle(self, widget=None, event=None): self.graphics_widget.remove_widget(self.scatter_baddy) if self.level == 1: self.next_battle() else: self.schedule(self.sounds['hero_song'].play, .5) self.schedule(self.sounds['hero_song'].play, 3) anim = Animation(x = 8 * X_BLOCK, duration = 4.5) self.image_hero.walk(30, 6 * X_BLOCK) anim.start(self.scatter_hero) anim.bind(on_complete = self.next_battle) def keep_hero_in_same_position(self, dt=None): self.image_hero.x = self.image_hero.x + 0.0 def stop_hero_motion(self, event=None, widget=None): Clock.unschedule(self.keep_hero_in_same_position) def next_battle(self, widget=None, event=None): self.scatter_baddy.rotation = 0 if self.level > 1: self.graphics_widget.remove_widget(self.scatter_hero) self.level = self.level + 1 self.schedule(self.setup_battle, 2.0) def remove_item(self, animation=None, widget=None): self.graphics_widget.remove_widget(widget) widget.canvas.clear() widget = None def update(self, widget=None, event=None): self.image_hero.angle = 0 self.image_baddy.angle = 0 try: self.current_gem.remove_widget(self.current_gem.children[-1]) self.scatter_hero.remove_widget(self.current_gem) except: pass anim1 = Animation(scale=self.baddy_size_ratio) anim2 = Animation(y= self.baddy_position[1]) anim3 = Animation(x= self.baddy_position[0]) anim4 = Animation(x = X_BLOCK) anim1.start(self.scatter_baddy) anim2.start(self.scatter_baddy) if self.time_limit < 0: anim3.start(self.scatter_baddy) anim4.start(self.scatter_hero) self.image_baddy.set_score(self.baddy_points) self.image_score.set_score(self.level_score) if self.scatter_baddy.scale > self.baddy_size_ratio: self.hero_celebrate() else: self.baddy_celebrate() if self.level_score < 0: self.image_score.flash(10) anim4.bind(on_complete = self.decide_next_stage) def decide_next_stage(self, widget=None, event=None): if self.baddy_points == 1: self.baddy_vanquished() elif self.attacks_tried == self.maximum_attacks: self.level_failed() elif self.baddy_points > 1 and (self.is_impossible(self.baddy_points)) and not self.potion_buttons: self.level_failed() else: self.hide_gems() self.show_gems() def talk_hero(self, dt=None): self.sounds['hero_talk'].play() self.image_hero.jump(60, 60) def talk_baddy(self, dt=None): self.sounds['baddy_talk'].play() self.image_baddy.jump(60, 60) def look_alive(self, dt=None, dummy=None): Clock.schedule_interval(self.image_baddy.look_alive, 1.5) Clock.schedule_interval(self.image_hero.look_alive, 2.0) def celebrate(self): self.image_hero.celebrate(60, 60) def hero_celebrate(self, widget=None, event=None): self.image_hero.celebrate(60, 60) def baddy_celebrate(self, widget=None, event=None): self.image_baddy.celebrate(60, 60) def load_sounds(self): self.sounds = {} for f in ["hero_charge", "hero_song", "hero_talk", "baddy_charge", "baddy_talk", "sword1", "sword2", "sword3"]: sound = SoundLoader.load(PATH + "sounds/" + f + '.wav') self.sounds[f] = MySound(sound) def load_gems(self): self.gem_sprites = [None] * 10 self.gem_sources = [""] * 10 for i in range(2,10,1): self.gem_sources[i] = PATH + "gems/" +"gem_0"+str(i)+".png" self.gem_sprites[i] = CoreImage(PATH + "gems/" +"gem_0"+str(i)+".png", color=(0,0,0,1)) def load_textures(self): self.textures = {} for f in ["splash", "bg_1", "bg_2", "bg_3", "bg_4", "bg_5", "bg_6", "bg_7", "bg_8", "bg_9"]: self.textures[f] = CoreImage(PATH+f+".png") #def load_sprites(self): # self.sprites = {} # for f in ["tree_green","tree_red","tree_yellow", "castle", "moon"]: # self.sprites[f] = CoreImage(PATH+f+".png") def calc_baddy_points(self, numbers, n_multiplications): product = 1 for i in range(n_multiplications): product = product * random.choice(numbers) return product #def is_prime(self, num): # if divide(num): # return False # return True def is_impossible(self, num): for weapon in self.weapons: if num % weapon == 0: return False return True
class MapServer(KalScenarioServer): json_filename = StringProperty('') scenariol = NumericProperty(-2) layers = ListProperty( ["mountains","rivers","cities","regions"] ) def search_data_files(self): blacklist = ('__init__.py', ) curdir = realpath(dirname(__file__)) for root, dirnames, filenames in walk(dirname(__file__)): for filename in filenames: if filename.startswith('.'): continue if filename in blacklist: continue filename = join(root, filename) filename = realpath(filename) if filename.startswith(curdir): filename = filename[len(curdir):] if filename.startswith('/'): filename = filename[1:] yield filename def __init__(self, *largs): self.resources = list(self.search_data_files()) resource_add_path(dirname(__file__)) Builder.load_file(join(dirname(__file__), 'map.kv')) super(MapServer, self).__init__(*largs) self.timeout = 0 self.timemsg = 0 self.players = {} # init client table for client in self.controler.clients: self.players[client] = { 'client': client, 'name': self.controler.get_client_name(client), 'ready': False, 'done': False, 'place': self.controler.metadata[client]['place'], 'count': 0 } #store mapitems and thumbs in order to display them on main screen #or remove them from clients self.mapitems = {} #filename: [client, index] self.thumbs = {} #index: [client, pos] #get map layers list from json self.load_json() def load_json(self): global layers curdir = join(dirname(__file__), 'data') json_filename = join(curdir, 'scenario.json') resource_add_path(curdir) with open(json_filename, 'r') as fd: data = load(fd) layers = data['layers'] def client_login(self, client): self.players[client]['ready'] = True def client_logout(self, client): del self.players[client] def start(self): '''Scenario start, wait for all player to be ready ''' super(MapServer, self).start() self.send_all('WAITREADY') self.state = 'waitready' def stop(self): Builder.unload_file(join(dirname(__file__), 'map.kv')) resource_remove_path(dirname(__file__)) def init_ui(self): size = map_coordinates[1] cx,cy = Window.center pos = (cx - size[0]/3.,cy - size[1]/3.) if scenariol == -2 : layers2 = [] elif scenariol == -1 : layers2 = layers else : layers2 = layers[int(scenariol)] self.layout = MapServerLayout() self.imagemap = imagemap = Map( server=True, size_hint=(None, None), size = size, layers = layers2 ) self.map_background = ImageWidget( source = 'data/map.png', size_hint = imagemap.size_hint, size = imagemap.size, ) self.scat = Scatter( size_hint = imagemap.size_hint, size = imagemap.size, center = pos, scale = .8, rotation = 0, do_translation = False, do_scale = False ) self.layout.add_widget(self.scat) self.scat.add_widget(self.map_background) self.scat.add_widget(self.imagemap) self.controler.app.show(self.layout) # # Client commands received # do_client_<command>(client, [...]) # def do_client_scenario(self, client, args): global scenariol scenariol = int(args[0]) def do_client_ready(self, client, args): self.players[client]['ready'] = True count = len([x for x in self.players.itervalues() if not x['ready']]) if count: self.msg_all('@%s ok, en attente de %d joueur(s)' % ( self.players[client]['name'], count)) def do_client_flagchange(self, client, args): filename = self.index2filename( int(args[0]) ) thumb_index = int(args[1]) #print "SERVER : do_client_flagchange: "+ str(client)+','+str(filename)+str(thumb_index) if filename not in self.mapitems.keys(): self.mapitems[filename] = [] if thumb_index not in self.thumbs.keys(): self.thumbs[thumb_index] = [None, (0,-300)] c = len( self.mapitems[filename] ) #hide from screen and free current thumb_index if thumb_index == -1 : #get thumb d = self.mapitems[filename] for i in d: cl,ti = i if cl == client : d = ti thumb = self.index2thumb(d) #remove thumb from screen self.scat.remove_widget(thumb) #save if (client, d) in self.mapitems[filename] : self.mapitems[filename].remove( (client, d) ) #remove mapitem from screen if len( self.mapitems[filename] ) == 0 : self.imagemap.hide_mapitem(filename) """ #add thumb to other clients self.display_thumb(client, d) self.display_mapitem(client,filename) """ #display elif c >= 0 : #store new self.mapitems[filename].append( (client, thumb_index) ) self.thumbs[thumb_index] = [client, self.thumbs[thumb_index][1] ] if c == 0: #display mapitem on main screen self.imagemap.display_mapitem(filename, True, (0,0,0,1)) thumb = self.create_and_add_item(client, thumb_index) """ #hide thumb on clients except client self.hide_thumb(client, thumb_index) self.hide_mapitem(client, filename) """ def index2filename(self,index): #trick to pass mapitem.filename (string) as a integer (protocol blocks strings..) return self.imagemap.data[index]['filename'] def create_and_add_item(self, client, index): th = self.index2thumb(index) thumb = self.imagemap.get_thumb(index) player_place = int(self.players[client]["place"])-1 r,g,b = map_colors[ player_place ] thumb.color = [r/255.,g/255.,b/255.,1.] thumb.pos = (0,-400) right_pos = self.imagemap.retrieve_pixels_location(thumb.item['filename']) if right_pos is not None : thumb.right_pos = right_pos else : thumb.right_pos = (0,0) self.scat.add_widget(thumb) if index in self.thumbs.keys() and thumb != None: thumb.center = self.thumbs[index][1] thumb.locked = True return thumb def do_client_pos(self, client, args): index = int(args[0]) x = int(args[1]) y = int(args[2]) thumb = self.index2thumb(index) if thumb is not None : thumb.center = (x,y) self.thumbs[index] = [client, (x,y)] def do_client_color(self, client, args): index = int(args[0]) a = int(args[1])/255. b = int(args[2])/255. c = int(args[3])/255. thumb = self.index2thumb(index) if thumb is not None : thumb.color = (a,b,c) def index2thumb(self,index): for child in self.scat.children: if isinstance(child,MapThumbnail) and child.index == index: return child return None def index2filename(self,index): data = self.imagemap.data return data[index]['filename'] def do_client_scale(self, client, scale): pass def do_client_rotate(self, client, rot): #anim = Animation(rotation = rot) #anim.start(self.scat) self.scat.rotation += int(rot[0]) # # Commands to send to clients # def hide_thumb(self, client, index): for cl in self.players.itervalues() : cl = cl['client'] if cl != client : self.send_to(cl, 'HIDETH %d' % index) def display_thumb(self,client, index): for cl in self.players.itervalues() : cl = cl['client'] if cl != client : self.send_to(cl, 'DISPLAYTH %d' % index) def hide_mapitem(self,client,filename): for cl in self.players.itervalues() : cl = cl['client'] if cl != client : self.send_to(cl, 'HIDEMAPITEM %s' % str(filename)) def display_mapitem(self,client,filename): for cl in self.players.itervalues() : cl = cl['client'] if cl != client : self.send_to(cl, 'DISPLAYMAPITEM %s' % str(filename)) def thumb_index_match_layer(self, index, client): filename = self.imagemap.data[index]['filename'] return self.filename_match_layer(filename, client) def filename_match_layer(self, filename, client): #print self.f1(self.layers) parts = filename.rsplit('-', 1) #print parts[0], self.layers_given, client if len(parts) != 2 : return False if client not in self.layers_given.keys(): return False if parts[0] != self.layers_given[ client ]: return False #print parts[0], self.layers_given, client return True def clear(self): self.send_all('CLEAR') #self clear as well self.mapitems = {} self.thumbs = {} self.layout.remove_widget(self.scat) self.scat.remove_widget(self.map_background) self.scat.remove_widget(self.imagemap) self.scat = '' self.imagemap = '' self.map_background = '' self.layout = '' # # State machine # def run_waitready(self): '''Wait for all player to be ready ''' ready = True for player in self.players.itervalues(): ready = ready and player['ready'] if not ready: return #create clients layout self.send_all('GAME1') self.timeout = time() + TIMER_1 self.send_all('TIME %d %d' % (time(), int(self.timeout))) #display sub-scenarii selector on clients self.send_all('SELECTOR') self.state = 'game0' def run_game0(self): if scenariol == -2: sleep(0.2) return #self.layout.remove_widget(self.selector) self.send_all('REMOVESELECTOR') self.init_ui() self.items_given = [] self.layers_given = {} affected = [-1] self.imagemap.layers = [] for client in self.controler.clients: place = int(self.players[client]['place']) - 1 self.send_to(client, 'COLOR %d %d %d' % map_colors[place]) self.send_to(client, 'LOGO %s' % map_logos[place]) #deal with "all layers" (one on each client) if not scenariol == -1 : layer = str(layers[scenariol]) else : l = len(layers) - 1 r = -1 if place > l : place = 0 else : while r in affected : r = int( random() * l ) affected.append(r) #print affected place = r layer = str(layers[place]) self.imagemap.layers = self.imagemap.layers + [layer] self.send_to(client, 'LAYER %s' % layer) self.layers_given[client] = layer self.send_to(client, 'MAPSIZE %d %d' % map_coordinates[1] ) self.send_to(client, 'MAPPOS %d %d' % map_coordinates[0]) #create map self.send_all('MAP') # deliver randomly index litems = len(self.imagemap.data) if litems: r = range(litems) allfinished = False while not allfinished: allfinished = True index = r.pop(randint(0, litems - 1)) litems -= 1 #print litems for client in self.controler.clients: player = self.players[client] if player['ready'] is False: continue if player['count'] > MAX_CLIENT_ITEMS - 1: continue if self.thumb_index_match_layer(index, client) == True : #print r, litems self.send_to(client, 'GIVE %d' % index) player['count'] += 1 self.items_given.append((client, index)) allfinished = allfinished and False break allfinished = allfinished and False if litems == 0 : allfinished = True self.state = 'game1' self.send_all('LAYOUTALL') def run_game1(self): '''First game, place items on the imagemap without ordering ''' if time() > self.timeout: self.state = 'reset_for_game2' return def run_reset_for_game2(self): '''Make correction on imagemap ! ''' # order ! index_sent = [] for thumb in self.scat.children: if not isinstance(thumb, MapThumbnail): continue #print thumb.item # are we far ? Check if thumb matches the place x,y = thumb.pos x += thumb.width/2. filename = self.imagemap.pos2mapitem(x,y) if filename is False : continue if filename == thumb.item['filename'] : #, thumb.item['filename'] for client in self.controler.clients: thumb.update_color(True) self.send_to(client, 'THVALID %d' % thumb.index) else : for client in self.controler.clients: thumb.update_color(False) thumb.shake() self.send_to(client, 'THNOTVALID %d' % thumb.index) index_sent.append(thumb.index) for client, index in self.items_given: if index in index_sent: continue self.send_to(client, 'THNOTVALID %d' % index) # do game 2 self.timeout = time() + TIMER_2 self.send_all('TIME %d %d' % (time(), int(self.timeout))) self.send_all('GAME2') self.send_all('GAME2') self.send_all('GAME2') self.state = 'game2' def run_game2(self): if time() > self.timeout: self.state = 'reset_for_game3' return def run_reset_for_game3(self): #move all thumbs to the right location on map #delete all existing items for child in self.scat.children[:]: if isinstance(child,MapThumbnail): self.scat.remove_widget(child) #place all thumbs on the map index = 0 clients = self.controler.clients #add all items to the map for item in self.imagemap.data : filename = item['filename'] if self.imagemap.filename_match_layer(filename): self.imagemap.display_mapitem(filename, True, (0,0,0,1)) item = self.create_and_add_item(clients.keys()[0] ,index) item.auto_color = False index +=1 #move thumbs to the right position self.send_all('PLACETHUMBS') self.send_all('GAME2') self.state = 'game3' self.timeout = time() + TIMER_3 self.send_all('TIME %d %d' % (time(), int(self.timeout))) def run_game3(self): if time() > self.timeout: self.clear() self.controler.switch_scenario('choose') self.controler.load_all()
class Field(Widget): app = ObjectProperty(None) style = DictProperty({'geometry_square_margin':0 }) activate_animations = BooleanProperty( False ) #internal variables squares = DictProperty( {} )#stores all the squares widgets geometry = DictProperty( {} )#geometry = squares' target relative positions and sizes on the field geometry_detailed = DictProperty( {} ) #real positions on the field geometry_squares = DictProperty( {} ) square_parameters = DictProperty( {} ) #defines the details of the square #stores all the geometry empty squares as widgets so that we can easily #compare their positions with the real squares apps = DictProperty( {} )#stores all the apps information video = ObjectProperty( None ) video_scatter = ObjectProperty( None ) video_size_pos = DictProperty( {} ) #bar_width = NumericProperty(135) spacing = NumericProperty(0.0) square_padding = NumericProperty(10) title = StringProperty('') def __init__(self,**kwargs) : super(Field, self).__init__(**kwargs) self.berkelium_is_installed = self.berkelium_is_installed() self.init_geometry() self.init_app() self.init_geometry_detailed() self.draw_geometry() self.apps = self.init_apps() self.init_square_parameters() self.init_squares() def get_field_size(self): width,height = self.geometry["screen_size"] spacing = s= self.spacing#0.012# = 0.02 #bar = self.bar_width / width width_wb = 0.90 #int(width) - bar#width without bar """ #Explanation of the math calculation #1) large = 3*small + 2*s large = 2*medium + s small = 2/3*medium - 1/3*s #2) width_wb = 4*s + large + medium + small #inject 1 into 2 width_wb = 4*s + 2*medium + s + medium + 2/3*medium - 1/3*s width_wb = s*(5 -1/3) + medium * (3+ 2/3) """ medium = (width_wb - s*(5 -1/3)) / (3+ 2/3) #get the rest large = 2*medium + s small = 0.66666*medium - 0.33333*s #large = self.geometry['large'] height = large *width# * float(large[0]) return width*width_wb, height*width_wb, small*width_wb, medium*width_wb, large*width_wb def get_size(self, layout_type) : if layout_type == 'icon': l,h = self.geometry["icon_px"] return (l,h) #Current screen size is applied width,height,small,medium,large = self.get_field_size() #in px small = small * width medium = medium * width large = large * width x = eval(layout_type) return (x,x) #return (l,h) def square_is_in_the_bar(self,square): return False def init_app(self): #Import the json file that defines it file_path = join(dirname(__file__), 'config') with open(file_path, 'r') as fd: config = loads(fd.read()) #print self.geometry if config is None: print 'Unable to load', file_path return self.title = config['title'] width,height,sm,me,la = self.get_field_size() self.title_label = Label(text = self.title, pos = (width*0.835,-20), font_size = 22, color = (.3,.3,.3,1), halign = 'right' ) self.add_widget(self.title_label) def init_geometry(self): #Import the json file that defines it file_path = join(dirname(__file__), 'field_geometry') with open(file_path, 'r') as fd: self.geometry = loads(fd.read()) #print self.geometry if self.geometry is None: print 'Unable to load', file_path return self.bar_width = int(self.geometry['bar_width']) #self.spacing = float(self.geometry['spacing']) def init_geometry_detailed(self): #calculates detailed geometry style = self.style #margin = style['geometry_square_margin'] #bar_width = self.bar_width #Current screen size is applied #width,height = self.size width,height,sm,me,la = self.get_field_size() screen_size = self.geometry['screen_size'] bar_width = int(screen_size[0]) - width margin_height = (int(screen_size[1]) - height*0.9)*0.5 print bar_width,height,margin_height if margin_height < 0: margin_height = 0 #print self.geometry['screen_size'][1], height, margin_height spacing = self.spacing #MODE AUTO : calculates every dimensions based on screen size, but for a specific arrow #draw small array = { 0:["small","small","small"], 1:["medium","medium"], 2:["large"] } x_hint = 0 key = 0 for i,list in array.iteritems(): size = self.get_size( list[0] ) l,h = size x_hint = x_hint + spacing index = 0 y_hint = 0 for j in list: #update geometry_detailed self.geometry[str(key)] = [x_hint,y_hint,list[0]] x = x_hint *width + bar_width y = y_hint *height + margin_height self.geometry_detailed[str(key)] = {'pos':(x,y),'size':(l,h),'layout_type':list[0]} index += 1 y_hint = (index) * (float(h)/height+spacing) key += 1 x = x + size[0] x_hint = x_hint + float(l)/width #print self.geometry #:insert that into field_geometry for specific array #and apply code below instead """ #in case we refer to all the dimensions inside the field_geometry file for key,val in self.geometry.iteritems() : if not key in ["screen_size","icon_px","vertical","bar_width","spacing"]: x,y,square_layout_type = val x = x * width + bar_width #+ self.x #+ margin y = y * height +margin_height#+ self.y #+ margin l,h = self.get_size(square_layout_type) #print (l,h) #update geometry_detailed self.geometry_detailed[key] = {'pos':(x,y),'size':(l,h), 'layout_type':square_layout_type } """ def draw_geometry(self): self.draw_empty_squares() def draw_empty_squares(self): #draw the shape of all empty locations on the field for key,val in self.geometry_detailed.iteritems() : id = key pos = val['pos'] size = val['size'] layout_type = val['layout_type'] self.geometry_squares[key] = GeometrySquare( geometry_id = int(id), pos = pos, size =size, layout_type = layout_type, do_scale = False, do_rotation = False, do_translation = False, auto_bring_to_front = False, ) self.add_widget( self.geometry_squares[id] ) #print self.geometry_squares def init_square_parameters(self): #Import the json files that defines each type of square for i in ['small','medium','large']: file_path = join(dirname(__file__), i) #print file_path with open(file_path, 'r') as fd: self.square_parameters[i] = loads(fd.read()) #print self.square_parameters[i] if self.square_parameters[i] is None: print 'Unable to load', file_path return #print self.square_parameters def init_apps(self): #Import the json file that defines apps file_path = join(dirname(__file__), 'apps','detail') apps = {} nb = 0 for subdir, dirs, files in walk(file_path): for file in files: with open(file_path +'/'+file, 'r') as fd: t = loads(fd.read()) if self.validate_web_app(t) : apps[str(nb)] = t print 'Load app: '+str(file) nb +=1 else : print 'Unable to load '+str(file)+', which has html/web content' if apps is None: print 'Unable to load', file_path return return apps def init_squares(self): #create and display squares for key,val in self.geometry_detailed.iteritems(): id = key pos = val['pos'] size = val['size'] layout_type = val['layout_type'] square = self.init_square(self.apps, key, pos, size, layout_type) if square is not None : self.add_square(square) def add_square(self, square): id = str(square.id) self.squares[id] = square self.add_widget( self.squares[id] ) #in case the screen is displayed vertically if self.geometry["vertical"] == 'True' : self.squares[id].rotation_90d -= 90 self.rotate(self.squares[id], -90) def remove_square(self,square, animation, touch): if animation : #remove some elements for i in square.children : square.remove_widget(i) kwargs = {'duration' : 1.1,'t':'in_quart'} anim = Animation(pos = touch.pos, size = (0,0), **kwargs ) anim.bind(on_complete = self.remove_square2 ) anim.start(square) else : self.remove_square2(1,square) def remove_square2(self,a,square): #avoid sound running after widget being removed and deleted if square.main_media_type == 'video': square.video.mute(1) self.remove_widget( square ) id = str(square.id) if id in self.squares.keys(): del(self.squares[id] ) def berkelium_is_installed(self): try : #from kivy.ext import load berkelium = load('berkelium', (1, 1)) return True except : return False def validate_web_app(self,app): #avoid the case of webpage without Berkelium installed #first case: main media is web main_media_type = app['main_media_type'] if (self.berkelium_is_installed == False and main_media_type == 'webpage') : return False #second case: layers are html layers = { "large" : str( app['layer_large'] ), "medium" : str( app['layer_medium'] ), "small": str( app["layer_small"] ) } for key,path in layers.iteritems(): if path[:4] in ['http','file']: if self.berkelium_is_installed == False : return False return True def init_square(self,apps,key,pos,size, layout_type): return Square( app =self.app, pos = pos, size = size, layout_type = layout_type, do_scale = False, geometry_id = int(key), icon_size = self.get_size('icon'), small_size = self.get_size('small'), medium_size = self.get_size('medium'), large_size = self.get_size('large'), id = key, title = apps[key]['title'], app_type = apps[key]['app_type'], color_text = apps[key]['color_text'], color_up = apps[key]['color_up'], color_down = apps[key]['color_down'], authors = apps[key]['authors'], main_media_type = apps[key]['main_media_type'], image_path = apps[key]['image_path'], video_path = apps[key]['video_path'], webpage_path = apps[key]['webpage_path'], layers = { "large" : str( apps[key]['layer_large'] ), "medium" : str( apps[key]['layer_medium'] ), "small": str( apps[key]["layer_small"] ) }, alternative_image_path = apps[key]['alternative_image_path'], main_description = apps[key]['main_description'] , long_description = apps[key]['long_description'], info_title = apps[key]['info_title'], info_text = apps[key]['info_text'], info_conclusion = apps[key]['info_conclusion'], square_parameters = self.square_parameters, padding = self.square_padding, berkelium_is_installed = self.berkelium_is_installed ) def geometry_square2square(self,key): ret = None g = self.geometry_squares for i,val in self.squares.iteritems() : #print val.geometry_id if g[key].collide_point(*val.center) : #if int(key) == val.geometry_id : ret = i return ret def shake_square(self, touch, key, intensity): square = self.squares[key] square.reshape_when_touch_down(touch,intensity) square.reshape_when_touch_up(touch) self.process_touch_up( square ) def add_app(self, key, touch): #function to be used by the bar to add an app to the field #print 'add_app_key :'+ key if key in self.squares.keys(): pass #self.shake_square(touch,key,6) else : #create the square square = self.init_square(self.apps,key,touch.pos, self.get_size('small'), 'small') #find matching location #focus on translation matcher = self.find_matcher(square)#matcher = the key of geometry_squares that fits the best if matcher is not None : #find the square that sits on matcher matching_square = self.geometry_square2square(matcher) #print "matcher: "+matcher #sq = geometry_id = str(square.geometry_id) self.add_square(square) self.app.bar.images[key].opacify() print 'add square '+key self.switch(square, matcher) if matching_square in self.squares.keys(): self.remove_square( self.squares[str(matching_square)], True, touch ) self.app.bar.images[str(matching_square)].unopacify() print 'remove square '+matching_square else : print matching_square +' not in self.squares' else : #destroy square self.remove_square(square, False, touch) #print self.squares.keys() #switch #remove current app from the field #send back the bar icon to its location def process_touch_up(self, square) : if square.process_touch_up_forbidden : return #focus on translation matcher = self.find_matcher(square) if matcher is not None : self.switch(square, matcher) else : self.push_back_into_place(square) #focus on rotation if len(square._touches)<=1 : return #calculate angle between previous pos and now a = square.rotation b = square.rotation_90d if a > (b + 45) : square.rotation_90d +=90 elif a < (b - 45) : square.rotation_90d -=90 rot = square.rotation_90d #fix an issue : flip 180 when smallest angle is negative smallest_angle = min( (180 - abs(a - b), abs(a - b)) ) if a > b : r=1 else : r=-1 if smallest_angle <0 : rot = rot + r*180 #print a,b,rot self.rotate(square, rot) def push_back_into_place(self,square) : id = str(square.geometry_id) if self.activate_animations : animation = Animation(pos = self.geometry_squares[id].pos, duration = 0.9,t='in_out_back') animation.start(square) else : square.pos = self.geometry_squares[id].pos def rotate(self,square, rotation) : animation = Animation(rotation = rotation, duration =0.3) animation.start(square) #square.rotation = rotation def find_matcher(self,square): geometry_id = str(square.geometry_id) geometry_squares = self.geometry_squares def find(x1,y1,target_is_bar) : matching_list = [] for key,val in geometry_squares.iteritems() : if not str(key) == geometry_id : if target_is_bar is False : if val.collide_point(x1,y1) : matching_list.append(key) l = len(matching_list) #one matches if l == 1: return matching_list[0] #several match, get the closest elif l>1 : closest_dist = 1000000000000000000000 closest_widget = 0 for key in matching_list : #get distance to target widget center x2,y2 = geometry_squares[key].center dist = Vector(x1,y1).distance( Vector(x2,y2) ) if dist < closest_dist : closest_dist = dist closest_widget = key return closest_widget #none matches elif l == 0 : return None #the center of the current widget is the reference x1,y1 = square.center m = find(x1,y1, False) return m def switch(self, square, matcher) : #switch position with another widget #self.activate_animations = False def get_layout_type(geometry_id) : return self.geometry[ str(geometry_id) ][2] def switch_layouts(): square.layout_type = target_layout target.layout_type = current_layout #if square.layout_type <> target.layout_type : square.refresh_layout(target_layout) target.refresh_layout(current_layout) def place_square(square): animate_square(square, target_layout, target_param,target_pos, target_size) square.refresh_layout(target_layout) square.geometry_id = int(matcher) def animate_square(square,layout_type,param,pos,size):#move, resize etc if self.activate_animations : kwargs = {'duration' : 1.1,'t':'in_quart'} square.process_touch_up_forbidden = True #switch pos and size animation = Animation(pos = pos, size = size, **kwargs) #+ Animation(size = target_size, duration = 0.5,t='in_quart') animation.bind(on_complete = self.adjust_position) animation.bind(on_complete = self.allow_process_touch_up) animation.start(square) #title size font_size = square.process_font_size( square.title ,int( param['title_label_font_size'] ) ) #text_size = (len(square.title)*font_size,None ) #text_size = (len(square.title)*font_size +100,None) animation = Animation(font_size = font_size, **kwargs) animation.start(square.title_label) #animation = Animation(width = len(square.title)*font_size, **kwargs) #animation.start(square.box2) #authors #animation = Animation(font_size = int( param['authors_label_font_size'] ), **kwargs) #animation.start(square.authors_label) #box top size animation = Animation(size_hint = param['box_top_size_hint'], **kwargs) animation.start(square.box_top) #box middle size animation = Animation(size_hint = param['box_middle_size_hint'], **kwargs) animation.start(square.box_middle) animation = Animation(size_hint = param['box_middle1_size_hint'], **kwargs) animation.start(square.box_middle1) animation = Animation(size_hint = param['box_middle2_size_hint'], **kwargs) animation.start(square.box_middle2) #box bottom size animation = Animation(size_hint = param['box_bottom_size_hint'], **kwargs) animation.start(square.box_bottom) #animation.bind(on_complete = self.switch_layouts) #launch button size animation = Animation(size = param["launch_button_size"], **kwargs) animation.start(square.launch_button) #vote button size animation = Animation(size = param["vote_button_size"], **kwargs) animation.start(square.vote_button) #vote feedback size animation = Animation(size = param["launch_button_size"], **kwargs) animation.start(square.fb) #spacing box_bottom_spacing = (self.get_size(layout_type)[0] -2*square.padding - param['vote_button_size'][0] - param['launch_button_size'][0]) * 0.97 animation = Animation(spacing = box_bottom_spacing, **kwargs) animation.start(square.box_bottom) else : square.size = size square.center = pos #get current properties of the target empty square to switch with target = self.geometry_squares[matcher] target_layout = get_layout_type(int(matcher)) target_param = self.square_parameters[target_layout] target_pos = target.pos target_size = target.size #target_size = self.get_size(target_layout) #if current place cannot be found if str(square.geometry_id) not in self.geometry.keys(): place_square(square) return #get current square properties #current_layout = square.layout_type #this way was buggy current_layout = square.layout_type#get_layout_type(square.geometry_id) current_param = self.square_parameters[current_layout] current_pos = self.geometry_squares[str(square.geometry_id)].pos current_size = square.size #current_size = self.get_size(current_layout)#target.size #get the target square target = 0 for key,val in self.squares.iteritems() : if val.geometry_id == int(matcher) : target = self.squares[key] break """ #adjust square pos in order to avoid jumping while changing layout if not target_size == current_size : if target_size > current_size : d = 1#and not target_size == current_size : elif target_size < current_size : d = -1 #get differencial vector between current square pos and future layout square pos #case of an empty destination if target == 0 and not target_layout == 'icon': if target_size > current_size : delta_square = Vector( (-d*target_size[0]*0.4, -d*target_size[1]*0.4) ) elif target_size < current_size : delta_square = Vector( (-d*target_size[0]*0.9, -d*target_size[1]*0.9) ) #case of an empty destination in the margin elif target_layout == 'icon': delta_square = Vector( (-d*current_size[0]*0.7, -d*current_size[1]*0.7) ) else : delta_square = ( d*Vector( target.pos ) - d*Vector( target.center ) ) rot = round(square.rotation,0) #print rot, delta_square a = (1,1) if rot == 90 : a = (-1,1) elif rot == 180 : a = (-1,-1) elif rot == 270 : a= (1,-1) b,c = a square.x += b * delta_square.x/2 square.y += c * delta_square.y/2 """ #fake a different pos to match user behaviour (i.e. placing the square in the center of the target) #square.center = square.pos #(changes with rotation .. ) #if empty location if target == 0 : place_square() return #square animate_square(square, target_layout, target_param, target_pos, target_size) #switch layouts switch_layouts() """ #adjust square pos in order to avoid jumping while changing layout if not target_size == current_size and not current_layout == 'icon': #case of an empty destination #if target == 0: if target_size > current_size : d = 1 elif target_size < current_size : d = -1 delta_target = d*Vector( target_pos ) - d*Vector( target.pos ) rot = round(target.rotation,0) a = (1,1) if rot == 90 : if target_size > current_size : a = (1,1) elif target_size < current_size : a = (-2,1) elif rot == 180 : a = (-1,-1) elif rot == 270 : a= (1,-1) b,c = a target.x += b * delta_target.x/2 target.y += c * delta_target.y/2 """ #target animate_square(target, current_layout, current_param, current_pos, current_size) #store pos target.geometry_id = square.geometry_id square.geometry_id = int(matcher) def allow_process_touch_up(self,a,square): square.process_touch_up_forbidden = False def switch_layouts(self, animation,square): def get_layout_type(geometry_id) : return self.geometry[ str(geometry_id) ][2] #get target layout target_layout = get_layout_type(square.geometry_id) square.layout_type = target_layout square.refresh_layout(target_layout) def adjust_position(self,a,square): gs= self.geometry_squares key = str(square.geometry_id) if not key in gs.keys():return match = gs[key] #pos size anim = Animation(pos = match.pos, size = match.size, duration = 0.2) anim.start(square) #layout #square.layout.pos = (square.padding, square.padding) #box bottom param = self.square_parameters[square.layout_type] box_bottom_spacing = (self.get_size(square.layout_type)[0] -2*square.padding - param['vote_button_size'][0] - param['launch_button_size'][0]) * 0.97 anim = Animation(pos = square.layout.pos, spacing = box_bottom_spacing, duration = 0.2) anim.start(square.box_bottom) def mute(self,uid): #mute all the square, unmute the given one for i in self.squares.itervalues(): if not i.uid == uid : i.mute() def play_video_fullscreen(self, video_path, pos, size, position): self.video = VideoPlayer2(source = video_path, options = {'position':position} ) self.video.bind(on_leave_fullscreen = self.on_leave_fullscreen) self.video.size = size #self.video.pos = pos self.video_scatter = Scatter(size = size, pos = pos) self.video_scatter.add_widget(self.video) self.add_widget(self.video_scatter) #store size and pos for later self.video_size_pos = {'size':size, 'pos':pos} Clock.schedule_once(self.video.start, 2.5) w,h = self.geometry['screen_size'] #(self.width - self.bar_width,self.height)#w,h,s,m,l = self.get_field_size()## if self.geometry['vertical'] == "True": #from kivy.graphics import Rotate """ rot = Rotate() rot.angle = 90 rot.axis =(0,0,1) """ #self.video.video.canvas.add(Rotate( 45,0,0,1 )) ''' with self.video.video.canvas : Rotate( 45,0,0,1 ) self.video.video.canvas.ask_update() #self.video.canvas.draw() ''' self.video_scatter.pos = self.pos #= (self.bar_width,0) self.video_scatter.rotation = -90 width = w w = h h = width #self.video_scatter.pos = self.center self.video_scatter.pos = (self.bar_width,w/2+self.bar_width/2)#center = (h/2,w/2-self.bar_width/2)#(self.center[0] +2*self.bar_width -25, w/2 +self.bar_width+25)# self.video_scatter.size = (w,h) self.video.size = (w,h) else : w = w - self.bar_width anim = Animation(size = (w,h),pos = (self.x +self.bar_width, self.y) ) anim.start(self.video_scatter) anim = Animation(size = (w,h) ) anim.start(self.video) def on_leave_fullscreen(self,a): if self.geometry['vertical'] == "True": self.video_scatter.rotation = 90 size = self.video_size_pos['size'] pos = self.video_size_pos['pos'] anim = Animation(size = size, pos = pos) anim.bind(on_complete = self.after_leaving_fullscreen) anim.start(self.video_scatter) anim = Animation(size = size) anim.start(self.video) def after_leaving_fullscreen(self,a,b): self.video.video.volume = 0 self.video_scatter.remove_widget(self.video ) self.remove_widget(self.video_scatter )
class KivyVisor(ModalView): MODO_NORMAL = 1 MODO_AJUSTADO_ALTURA = 2 MODO_AJUSTADO_ANCHO = 3 def __init__(self, comicBook, **kwargs): super(KivyVisor, self).__init__(**kwargs) self.modoVisualizacion = KivyVisor.MODO_NORMAL self.scatter = Scatter() self.scatter.center = Window.center print("scatter center: {}".format(self.scatter.center)) self.bind(on_touch_down=self.on_touch) self.comic = comicBook self.comic.openCbFile() self.imagenPagina = self.comic.getImagePage() self.imagenPagina.size = self.imagenPagina.texture_size self.imagenPagina.size_hint = (None, None) self.scatter.size_hint = (None, None) self.scatter.size = self.imagenPagina.texture_size self.scatter.center = Window.center print("image size: {}".format(self.imagenPagina.size)) print("scatter center: {}".format(self.scatter.center)) print("window center: {}".format(Window.center)) self.scatter.pos_hint = (None, None) self.scatter.add_widget(self.imagenPagina) self.scatter.do_rotation = False self.scatter.center = (0, 0) self.imagenPagina.center = (0, 0) '''recordar que la imagen se mueve desde el centro. y la posicion es relativa al centro del contenedor en este caso es el scatter''' self.imagenPagina.pos = (0, Window.center[1] - self.imagenPagina.size[1] / 2) self.add_widget(self.scatter) # self.scatter.x = 1111 print("scatter center: {}".format(self.scatter.center)) print("scatter Heiht: {}".format(self.scatter.height)) Window.bind(on_motion=self.on_motion) Window.bind(on_resize=self.on_sizeWindow) def on_sizeWindow(self, arg1, arg2, arg3): self.__refreshPage__() def on_motion(self, etype, motionevent, other): if other.is_mouse_scrolling: if other.button == 'scrolldown': self.scatter.y -= 10 if other.button == 'scrollup': self.scatter.y += 10 else: # print(self.scatter.pos) print("pos imagen :{}".format(self.imagenPagina.pos)) print("tamaño scatter :{}".format(self.scatter.size)) # help(other) # print(motionevent) # print(other) # print("Capturan scroll") def on_touch(self, obj, event): ''' vamos a capturar eventos en estas zonas ************************* *1* *0* *2* *** *** *** * * * * * * * * *3* *4* * * * * * * * * * * *** *** *5* *6* ************************* :param widget: :param event: :return: ''' #zona1 = ((0, Window.width * 0.1), (Window.height, (Window.height - Window.height * 0.1))) #zona2 = ((Window.width - Window.width * 0.1, Window.width), (Window.height, (Window.height - Window.height * 0.1))) zona0 = ((Window.width * 0.5 - Window.width * 0.1, Window.width * 0.5 + Window.width * 0.1), (Window.height - Window.height * 0.1, Window.height)) zona3 = ((0, Window.width * 0.1), (Window.height * 0.1 + Window.height * 0.5, Window.height * -0.1 + Window.height * 0.5)) zona4 = ((Window.width - Window.width * 0.1, Window.width), (Window.height * 0.1 + Window.height * 0.5, Window.height * -0.1 + Window.height * 0.5)) if (zona3[0][0] < event.pos[0] and event.pos[0] < zona3[0][1]) and ( event.pos[1] < zona3[1][0] and event.pos[1] > zona3[1][1]): self.scatter.remove_widget(self.imagenPagina) self.comic.gotoPrevPage() self.__refreshPage__() if (zona4[0][0] < event.pos[0] and event.pos[0] < zona4[0][1]) and ( event.pos[1] < zona4[1][0] and event.pos[1] > zona4[1][1]): self.scatter.remove_widget(self.imagenPagina) self.comic.gotoNextPage() self.__refreshPage__() if (zona0[0][0] < event.pos[0] and event.pos[0] < zona0[0][1]) and ( zona0[1][0] < event.pos[1] and event.pos[1] < zona0[1][1]): box = GridLayout(cols=5) botonAncho = Button(text="Ancho") botonAncho.bind(on_press=self.ancho) box.add_widget(botonAncho) botonAjustarAlto = Button(text="Alto") botonAjustarAlto.bind(on_press=self.ajustarAlto) box.add_widget(botonAjustarAlto) botonCentrado = Button(text="normal") botonCentrado.bind(on_press=self.sinAjuste) box.add_widget(botonCentrado) botonRotar = Button(text="Rotar") botonRotar.bind(on_press=self.rotar) box.add_widget(botonRotar) p = Popup(title='Comic View popup', size_hint=(None, None), size=(400, 150)) p.add_widget(box) p.open() def ancho(self, event): print(Window.width) self.modoVisualizacion = KivyVisor.MODO_AJUSTADO_ANCHO self.scatter.scale = Window.width / self.imagenPagina.width self.__refreshPage__() # # self.scatter.pos = (0, 0) def __refreshPage__(self): self.scatter.remove_widget(self.imagenPagina) self.imagenPagina = self.comic.getImagePage() self.scatter.center = self.imagenPagina.center = Window.center self.imagenPagina.size = self.imagenPagina.texture_size self.scatter.add_widget(self.imagenPagina) if self.modoVisualizacion == KivyVisor.MODO_NORMAL: self.imagenPagina.pos = (0, Window.center[1] - self.imagenPagina.size[1] / 2) elif self.modoVisualizacion == KivyVisor.MODO_AJUSTADO_ALTURA: self.imagenPagina.pos = (0, 0) elif self.modoVisualizacion == KivyVisor.MODO_AJUSTADO_ANCHO: self.imagenPagina.pos = (0, (self.scatter.scale, ( Window.center[1] - (self.imagenPagina.size[1] / 2) * self.scatter.scale))) print("Centro window {} size_y {} factor {} new_pos_Y {}".format( Window.center[1], self.imagenPagina.size[1], self.scatter.scale, (Window.center[1] - (self.imagenPagina.size[1] / 2) * self.scatter.scale))) def ajustarAlto(self, event): print("alto: {}".format(Window.height)) self.modoVisualizacion = KivyVisor.MODO_AJUSTADO_ALTURA self.scatter.scale = Window.height / self.imagenPagina.height self.__refreshPage__() # # self.scatter.pos = (0, 0) def rotar(self, event): print("rotar") def sinAjuste(self, event): self.scatter.scale = 1 self.scatter.pos = (0, 0) print("centrado") self.scatter.center = Window.center
class MyApp(App): def build(self): Window.bind(on_key_down=self.on_key_down) self.loadData() self.activeTrack = None self.currentLayer = 0 self.appstructure = FloatLayout() width, height = Window.size self.menu = Menu() self.menu.onNewTrack(self.newTrack) self.menu.onNewPoint(self.newPoint) self.menu.onDeletePoint(self.deletePoint) self.menu.onSetClass(self.setClass) self.menu.onFindUnclassified(self.jumpToUnclassified) self.menu.onShowStats(self.showStats) self.menu.onSave(self.save) self.core = Scatter(auto_bring_to_front=False) self.core.add_widget(self.getCurrentLayer().getContents()) self.appstructure.add_widget(self.core) self.appstructure.add_widget(self.menu.getContents()) self.zoomSlider = Slider(orientation='vertical', min=1, max=10, size_hint=(0.05,1),pos_hint={'x':0.95}) self.zoomSlider.bind(on_touch_move=self.on_touch_move) self.zoomSlider.bind(on_touch_down=self.on_touch_down) self.zoomSlider.bind(on_touch_up=self.on_touch_up) self.appstructure.add_widget(self.zoomSlider) self.imagelabel = Label(text=self.getCurrentLayer().getSource(), size_hint=(1,0.05), pos_hint={'y':0}) self.appstructure.add_widget(self.imagelabel) self.zooming = False return self.appstructure def loadImages(self): def isImage(fname): for ext in [".png", ".jpg", ".tiff", ".jpeg", ".bmp"]: if fname.lower().endswith(ext): return True return False self.layers = [] for img in sortByFirstNumber(listdir("images")): if isImage(img): self.layers.append(Layer("images/"+img)) def loadData(self): self.loadImages() self.tracks = [] try: trackreps = load(open("saveFile.data")) except: return for trackrep in trackreps: track = Track(self.setActive) for pointrep in trackrep['points']: point = Point(pointrep[1]) track.addPoint(point, pointrep[0]) self.layers[pointrep[0]].addPoint(point) point.setPos(pointrep[1]) track.setClassification(trackrep['classification']) track.setInactive() self.tracks.append(track) def save(self): self.saveTo("backup-"+datetime.today().strftime("%Y-%m-%d-%H-%M-%S")+".data") self.saveTo("saveFile.data") def saveTo(self, fileName): #save to file ... def trackRepresentation(track): trackrep = {'classification':track.getClassification()} trackrep['points'] = [] for layer in range(len(self.layers)): point = track.getPointForLayer(layer) if point: trackrep['points'].append((layer, point.getPos())) return trackrep savetracks = [] for track in self.tracks: savetracks.append(trackRepresentation(track)) print savetracks dump(savetracks, open(fileName, 'w+')) def on_touch_down(self, slider, ev): if (slider.collide_point(ev.pos[0], ev.pos[1])): self.zooming = True def on_touch_move(self, slider, ev): if (self.zooming): zoom = self.zoomSlider.value self.core.scale = zoom def on_touch_up(self, slider, ev): self.zooming = False def showStats(self, *args): classCounts = {} for classification in classesToColours: classCounts[classification] = 0 for track in self.tracks: if track.getClassification(): classCounts[track.getClassification()] += 1 text = "" for classification in classCounts: text += " %s : %s \n"%(classification,classCounts[classification]) popup = Popup(title='Statistics', content=Label(text=text), size_hint=(None, None), size=(400, 400)) popup.open() def setClass(self, classification): if (self.activeTrack): self.activeTrack.setClassification(classification) def setActive(self, track): if (self.activeTrack): self.activeTrack.setInactive() self.activeTrack = track track.setActive() def newPoint(self): if (self.activeTrack == None): return point = Point((width/2,height/2)) if (self.activeTrack.addPoint(point, self.currentLayer)): self.getCurrentLayer().addPoint(point) def deletePoint(self): if (self.activeTrack == None): return point = self.activeTrack.getPointForLayer(self.currentLayer) if (point == None): return if not(self.activeTrack.deletePoint(self.currentLayer)): return self.getCurrentLayer().deletePoint(point) if (self.activeTrack.getClassification() == None): self.tracks.remove(self.activeTrack) self.activeTrack = None def newTrack(self): track = Track(self.setActive) point = Point((width/2, height/2)) track.addPoint(point, self.currentLayer) track.setActive() track.setClassification('unclassified') self.tracks.append(track) self.setActive(track) self.getCurrentLayer().addPoint(point) def getCurrentLayer(self): return self.layers[self.currentLayer] def jumpToUnclassified(self): for track in self.tracks: if track.getClassification() == 'unclassified': for i, layer in enumerate(self.layers): if track.getPointForLayer(i): self.setActive(track) self.swapLayer(self.getCurrentLayer(), layer) self.currentLayer = i return popup = Popup(title='', content=Label(text="No unclassified tracks found!"), size_hint=(None, None), size=(400, 400)) popup.open() def moveUpLayer(self): if (self.currentLayer < (len(self.layers) - 1)): original = self.getCurrentLayer() self.currentLayer += 1 new = self.getCurrentLayer() self.swapLayer(original, new) def moveDownLayer(self): if (self.currentLayer > 0): original = self.getCurrentLayer() self.currentLayer -= 1 new = self.getCurrentLayer() self.swapLayer(original, new) def swapLayer(self, old, new): if (old == new): return self.imagelabel.text = new.getSource() self.core.add_widget(new.getContents()) self.core.remove_widget(old.getContents()) # current transform is layer * user layer = new.getTransform() transform = self.core.transform user = transform.multiply(layer.inverse()) # put back to start self.core.apply_transform(self.core.transform_inv) # apply layer transformation self.core.apply_transform(old.getTransform()) # reapply user transformation self.core.apply_transform(user) def on_key_down(self, instance, code, *args): if (code == 275): self.moveUpLayer() if (code == 276): self.moveDownLayer()
class CompasTest(App): def Hardware(self, *args): try: self.Encender() self.tetha = 0 print "Encendiendo compas" if True: print "Empezando lectura" Hilo1 = Clock.schedule_interval(self.Lectura, 1 / 20.) Hilo2 = Clock.schedule_interval(self.Empareja_todo, 1 / 20.) self.Disparar() return True except NotImplementedError: import traceback traceback.print_exc() status = "No reconoce el sensor magnetico en su dispositivo" print "No reconoce el compas" return False def Encender(self, *args): print "Se esta encendiendo" compass.enable() def Apagar(self, *args): print "Se esta apagando" compass.disable() def Lectura(self, *args): x, y, z = compass.orientation try: xf = round(x, 3) yf = round(y, 3) zf = round(z, 3) self.Bx = xf self.By = yf self.Bz = zf lbl1.text = "Sensor de Campo Magnetico \nBx = " + str( xf) + "\n" + "By = " + str(yf) + "\n" + "Bz = " + str(zf) except: print "No hay ningun dato todavia espere" def Empareja_todo(self, *args): try: self.Clasifica_tetha() self.Dispercion1() self.Disparar() except: print "Fallo al emparejar todo" def Dispersion1(self): self.dis1 = Scatter() self.dis1.pos = 100, 300 #self.dis1.pos = random.randrange(100,680), 100 self.dis1.size_hint = None, None #self.dis1.size = 100, 100 self.dis1.do_rotation = False self.dis1.do_scale = False self.dis1.do_translation = False self.dis1.scale = 1.8 lbl2.text = "HACK-VISION DEMO \n Angulo tetha: " + str(self.tetha) self.dis1.rotation = self.tetha + 90 def Clasifica_tetha(self): #Sentido MAnecillas del reloj #Primer cuadrante try: self.tetha != None if ((self.Bz > -25) & (self.Bz <= 0) & (self.Bx <= 0) & (self.By <= 0)): tetha = (self.Bz * 90) / 25 + 90 self.tetha = round(tetha, 3) return self.tetha #segundo cuadrante if ((self.Bz > 0) & (self.Bz <= 25) & (self.Bx <= 0) & (self.By <= 0)): tetha = self.Bz * 90 / 25 + 90 self.tetha = round(tetha, 3) return self.tetha #tercer cuadrante if ((self.Bz > 0) & (self.Bz <= 25) & (self.Bx >= 0) & (self.By <= 0)): tetha = (-1) * (self.Bz * 90 / 25 - 270) self.tetha = round(tetha, 3) return self.tetha #Quinto cuadrante if ((self.Bz > -25) & (self.Bz <= 0) & (self.Bx >= 0) & (self.By <= 0)): tetha = (-1) * (self.Bz * 90 / 25 - 270) self.tetha = round(tetha, 3) return self.tetha except: print "Nada" def Dispersion2(self): self.dis2 = Scatter() self.dis2.pos = -90, -50 #self.dis2.pos = random.randrange(100,680), 100 self.dis2.size_hint = None, None # self.dis2.size = 86, 86 self.dis2.do_rotation = False self.dis2.do_scale = False self.dis2.do_translation = False self.dis2.rotation = 0 self.dis2.scale = 1.7 def Animacion1(self, *args): global Anim lol = Widget() Anim = Image() Anim.source = "img/fondo_brujula.png" # Anim.size = 700,700 #Anim.source = "img/caballo.zip" #Anim.anim_delay=(0.15) # Anim.pos_hint= {"x": -0.1, "center_y": -1} # Anim.pos = 10, 10 #Anim.pos = random.randrange(100,680), random.randrange(100,460) self.dis1.add_widget(Anim) lol.add_widget(self.dis1) self.widget1.add_widget(lol) def Camara(self, *args): # self.Dispersion2() camwidget = Widget() #Create a camera Widget cam = Camera() #Get the camera cam.resolution = (640, 480) cam.size = 1000, 800 cam.pos = (-100, -100) cam.play = True #Start the camera camwidget.add_widget(cam) # self.widget1.add_widget(camwidget) self.dis2.add_widget(camwidget) self.widget1.add_widget(self.dis2) def Label1(self): global lbl1 lbl1 = Label() # lbl1.text = "Esperando instrucciones:" lbl1.pos = 200, 100 self.widget1.add_widget(lbl1) def Label2(self): global lbl2 lbl2 = Label() # lbl2.text = "Esperando instrucciones:" lbl2.pos = 200, 10 self.widget1.add_widget(lbl2) def Disparar(self): self.x = 0 Hilo2 = Clock.schedule_interval(self.disparo1, 0.9) # self.disparo1() def disparo1(self, *args): if self.opcion == 1: self.dis1.remove_widget(Anim) self.widget1.remove_widget(self.dis1) self.opcion = 0 if self.opcion == 0: self.Dispersion1() self.Animacion1() self.x = self.x + 10 self.opcion = 1 def build(self): self.opcion = 0 self.widget1 = Widget() self.Dispersion2() self.Camara() self.Label1() self.Label2() self.Hardware() return self.widget1
class AnalogeGauge(Widget): ''' Gauge class ''' unit = NumericProperty(1.8) size_text = NumericProperty(10) value = BoundedNumericProperty(0, min_value=0, max_value=100, errorvalue=0) start_angle = BoundedNumericProperty(90, min_value=-360, max_value=360, errorvalue=0) angle_width = BoundedNumericProperty(180, min_value=0, max_value=360, errorvalue=0) min_value = NumericProperty(0) max_value = NumericProperty(100) rotate_clock = BooleanProperty(True) file_background = StringProperty("cadran.png") file_gauge = StringProperty("") file_needle = StringProperty("") half_widget_view = BooleanProperty(False) padding = BoundedNumericProperty(10, min_value=0, max_value=360, errorvalue=0) mark_count = BoundedNumericProperty(10, min_value=0, max_value=360, errorvalue=0) mark_sub_count = BoundedNumericProperty(10, min_value=0, max_value=100, errorvalue=0) show_middle_marks = BooleanProperty(True) show_sub_marks = BooleanProperty(True) mark_size = BoundedNumericProperty(20, min_value=0, max_value=300, errorvalue=0) mark_mid_size = BoundedNumericProperty(15, min_value=0, max_value=300, errorvalue=0) mark_sub_size = BoundedNumericProperty(10, min_value=0, max_value=300, errorvalue=0) mark_color = ColorProperty('#ffffffff') mark_sub_color = ColorProperty('#ffffffff') mark_mid_color = ColorProperty('#ffffffff') needle_color = ColorProperty('#ff0000ff') glab_color = ColorProperty('#ff0000ff') def __init__(self, **kwargs): super(AnalogeGauge, self).__init__(**kwargs) self._gauge_widget = Widget() self._gauge = self._gauge_widget self._needle_widget_safe = Widget() self._needle_widget = self._needle_widget_safe self._form_processor_constants() self._needle = Scatter(size=self.size, do_rotation=False, do_scale=False) self._background_widget = Widget() self._background = Scatter(size=self.size, do_rotation=False, do_scale=False) self._glab = Label(font_size=self.size_text, markup=True, font_name='digital') self._needle.add_widget(self._needle_widget) self.add_widget(self._background) self.add_widget(self._gauge) self.add_widget(self._glab) self.add_widget(self._needle) self.bind(pos=self._update) self.bind(size=self._update) self.bind(value=self._turn) self.bind(file_gauge=self._reform_widget_graphics) self.bind(file_needle=self._reform_widget_graphics) self.bind(file_background=self._reform_widget_graphics) self.bind(min_value=self._form_processor_constants) self.bind(rotate_clock=self._form_processor_constants) self.bind(max_value=self._form_processor_constants) self.bind(start_angle=self._form_processor_constants) self.bind(angle_width=self._form_processor_constants) self.bind(mark_color=self._create_gaudge) self.bind(mark_sub_color=self._create_gaudge) self.bind(mark_mid_color=self._create_gaudge) self.bind(show_middle_marks=self._create_gaudge) self.bind(show_middle_marks=self._create_gaudge) self.bind(mark_count=self._create_gaudge) self.bind(mark_sub_count=self._create_gaudge) self.bind(needle_color=self._create_needle) self.bind(padding=self._update) self._update() self._reform_widget_graphics() self._turn() def _form_processor_constants(self, *args): self.property('value').set_min(self, self.min_value) self.property('value').set_max(self, self.max_value) self.unit = self.angle_width / abs(self.max_value - self.min_value) * ( -1 if self.rotate_clock else 1) #print(self.unit, self.angle_width) def _reform_widget_graphics(self, *args): #print(self.size) if self.file_gauge: self.remove_widget(self._gauge) self._gauge = get_module_resource_path(self.file_gauge, size=self.size, resource_package=__name__) self.add_widget(self._gauge) else: self.remove_widget(self._gauge) self._gauge = self._gauge_widget self.add_widget(self._gauge) if self.file_background: self._background.remove_widget(self._background_widget) self._background_widget = get_module_resource_path( self.file_background, size=self.size, resource_package=__name__) self._background.add_widget(self._background_widget) if self.file_needle: self._needle.remove_widget(self._needle_widget) self._needle_widget = get_module_resource_path( self.file_needle, size=self.size, resource_package=__name__) self._needle.add_widget(self._needle_widget) else: self._needle.remove_widget(self._needle_widget) self._needle_widget = self._needle_widget_safe self._needle.add_widget(self._needle_widget) def _turn(self, *args): ''' Turn needle, 1 degree = 1 unit, 0 degree point start on 50 value. ''' self._needle.center_x = self._gauge.center_x self._needle.center_y = self._gauge.center_y self._needle.rotation = self.start_angle + (self.value - self.min_value) * self.unit #print(self.start_angle, self.unit,self.value,self.min_value,self._needle.rotation) self._glab.text = "[b]{0:.0f}[/b]".format(self.value) def _create_needle(self, *args): if self._needle_widget == self._needle_widget_safe: self._needle_widget_safe.canvas.clear() with self._needle_widget_safe.canvas: Color(*self.needle_color) Line(points=(*self._needle_widget_safe.center, self._needle_widget_safe.center_x, self._needle_widget_safe.center_y + self.circle_radius)) Line(points=(*self._needle_widget_safe.center, self._needle_widget_safe.center_x, self._needle_widget_safe.center_y + self.circle_radius - 20), width=1.5) Ellipse(pos=(self._needle_widget_safe.center_x - 5, self._needle_widget_safe.center_y - 5), size=(10, 10)) def _create_gaudge(self, *args): if self._gauge == self._gauge_widget: self._gauge_widget.canvas.clear() if self.mark_count > 0: delta_mark = self.angle_width / self.mark_count mark_width = 10 mark_end = min(self.width, self.height) / 2 with self._gauge_widget.canvas: if self.show_sub_marks: Color(*self.mark_sub_color) sub_delta_mark = delta_mark / self.mark_sub_count count = self.mark_count * self.mark_sub_count + 1 sub_start_size = self.circle_radius - self.mark_sub_size for i in range(count): Line(points=get_mark_vector( *self.circle_pos, sub_start_size, self.mark_sub_size, self.start_angle - sub_delta_mark * i)) if self.show_middle_marks: Color(*self.mark_mid_color) sub_delta_mark = delta_mark / 2 count = self.mark_count * 2 + 1 sub_start_size = self.circle_radius - self.mark_mid_size for i in range(count): Line(points=get_mark_vector( *self.circle_pos, sub_start_size, self.mark_mid_size, self.start_angle - sub_delta_mark * i)) Color(*self.mark_color) start_size = self.circle_radius - self.mark_size for i in range(self.mark_count + 1): Line(points=get_mark_vector( *self.circle_pos, start_size, self.mark_size, self.start_angle - delta_mark * i)) def _update(self, *args): ''' Update gauge and needle positions after sizing or positioning. ''' if self.half_widget_view: self.circle_radius = min(*self.size) - self.padding * 2 self.circle_size = (self.circle_radius, self.circle_radius) self.circle_pos = (self.center_x, self.center_y - self.circle_radius / 2) self._bg_pos = (self.x, self.y - self.circle_radius / 2) else: self.circle_radius = min(*self.size) / 2 - self.padding self.circle_size = (self.circle_radius, self.circle_radius) self.circle_pos = self.center self._bg_pos = (self.x, self.y) self._needle.size = self.size self._gauge.size = self.size self._gauge.pos = self.pos self._gauge.center = self.circle_pos self._needle.pos = (self.x, self.y) self._needle.center = self.circle_pos self._background.pos = self._bg_pos self._needle_widget.size = self.size self._background_widget.size = self.size self._glab.center_x = self._gauge.center_x self._glab.center_y = self.center_y + (self.height / 4) self._create_gaudge() self._create_needle() def set_animate(self, value, easing='in_out_quad', speed=1): from kivy.animation import Animation Animation(value=value, duration=speed, t=easing).start(self)