def __init__(self, cpos, radius, texture=None): super(TimedCEllipse, self).__init__() # save position self.cpos = cpos self.r = radius self.width = radius * .2 # code for creating the Line self.rcolor = Color(*kGemRingColor, mode="rgba") self.rrgb = kGemRingColor PushMatrix() self.add(self.rcolor) self.angle = 0 self.ring = Line(circle=(*self.cpos, self.r, self.angle, 360), width=self.width, cap='none') self.add(self.ring) # code for creating the circle self.ccolor = Color(*kGemCircleColor) self.add(self.ccolor) csize = (2 * radius - self.width, ) * 2 self.circ = CEllipse(cpos=cpos, csize=csize) self.add(self.circ) PopMatrix()
class GearLocation(InstructionGroup): def __init__(self, position, size, x, y, gear_type): super(GearLocation, self).__init__() self.x = x self.y = y self.type = gear_type self.add(self.get_color()) self.location_holder = CEllipse(cpos=position, csize=(size, size)) self.add(self.location_holder) def on_layout(self, pos, size): self.location_holder.set_cpos(pos) self.location_holder.set_csize((size, size)) def get_color(self): if self.type == 'volume': return colors["light_red"] elif self.type == 'pitch': return colors["light_orange"] elif self.type == 'tempo': return colors["light_purple"] elif self.type == 'instrument': return colors["light_yellow"] else: return Color(255, 255, 255)
def timbre_to_shape(self, timbre, pos): if timbre == 'sine': return CEllipse(cpos=pos, size=self.norm.nt((80, 80)), segments=20) elif timbre == 'triangle': return CEllipse(cpos=pos, size=self.norm.nt((90, 90)), segments=3) elif timbre == 'square': return CRectangle(cpos=pos, size=self.norm.nt((80, 80))) elif timbre == 'sawtooth': # square rotated 45 degrees return CEllipse(cpos=pos, size=self.norm.nt((90, 90)), segments=4)
def __init__(self, position, size, x, y, gear_type): super(GearLocation, self).__init__() self.x = x self.y = y self.type = gear_type self.add(self.get_color()) self.location_holder = CEllipse(cpos=position, csize=(size, size)) self.add(self.location_holder)
def __init__(self, x, y, size, num_teeth, gear_type, gear_value, storage_pos, box_pos, gear_id, background_color=Color(0, 0, 0), part=0): super(Gear, self).__init__() # part is 0 for melody and 1 for bassline self.part = part self.type = gear_type # 'volume', 'pitch', 'speed', 'instrument', 'center' self.color = self._get_color() self.value = gear_value self.x = x self.y = y self.storage_pos = storage_pos self.box_pos = box_pos self.gear_id = gear_id self.size = size self.add(self.color) self.main_circle = CEllipse(cpos=self.storage_pos, csize=(self.size, self.size)) self.add(self.main_circle) self.middle_size = self.size / 2 self.teeth = [] self.num_teeth = num_teeth self.add_teeth(self.storage_pos, self.num_teeth) self.is_draggable = False self.in_music_box = False self.touch_x_diff = None self.touch_y_diff = None self.time = 0 self.rpm = 0.1 self.is_rotating = False
def __init__(self, initial_val, image_pos, image_size): super(Slider, self).__init__() self.value = initial_val self.min_val = 1 self.max_val = MAX_NUM_OF_DOMINO_SETS self.image_size = image_size self.image_pos = image_pos # self.percent = (self.value - self.min_val) / (self.max_val - self.min_val) self.line = Line(points=[ image_pos[0], image_pos[1] - Window.height // 20, image_pos[0] + image_size[0], image_pos[1] - Window.height // 20 ], width=10) self.add(self.line) dim_size = min(0.03 * Window.width, 0.03 * Window.height) self.add(Color(rgb=(235 / 255, 74 / 255, 90 / 255))) self.slider_knob = CEllipse( cpos=(self.image_pos[0] + (((self.value - self.min_val) / (self.max_val - self.min_val)) * self.image_size[0]), self.image_pos[1] - Window.height // 20), csize=(dim_size, dim_size)) self.knob_selected = False self.add(self.slider_knob)
def __init__(self, centerPos, noteLength, quarterNoteWidth): super(ComposeNoteShape, self).__init__() #noteLength passed in incase we want to change shape based on length w = Window.width self.height = quarterNoteWidth * abs(noteLength) self.width = quarterNoteWidth * abs(noteLength) leftX = centerPos[0] - (self.width / 2) botY = centerPos[1] - (self.height / 2) self.shape = None if noteLength < 0: self.shape = Rectangle(pos=(leftX, botY), size=(self.width, self.height)) else: self.shape = CEllipse(cpos=centerPos, csize=(self.width, self.height), segments=40) colorChange = leftX / w hue = .6 + .5 * (colorChange) self.color = Color(hsv=(hue, 1, 1), a=1) self.add(self.color) self.add(self.shape)
def __init__(self, bpm): super(NowBar, self).__init__() self.bpm = bpm # color the cursor grey self.color = Color(*kCursorDefaultColor) self.add(self.color) # save position and size self.xpos = PlaceOnBeat(.75) #kTrackLowerLimit self.xstart = self.xpos self.ypos = kGemBarYPos self.csize = kCursorSize # draw the cursor as a circle cpos = (self.xpos, self.ypos) self.cursor = CEllipse(cpos=cpos, csize=self.csize, texture=Image(kNowBarPng).texture) self.add(self.cursor) # limits that NowBar will be moving within, correlates with length of gem bar self.lim_lo = kTrackLowerLimit self.lim_hi = Window.width - self.lim_lo # save time for animation, by starting large, the cursor will maintain its size self.t = kCursorMaxTime # save speed of the cursor self.v = BpmToPixels(bpm) # initialize position of the NowBar self.active = True # hold callback that will be used to indicate reaching the end of the line self.end_cb = None
def __init__(self, x, y, storage_pos, box_pos, type, size, background_color): super(GearCenter, self).__init__() self.color = background_color self.size = size self.storage_pos = storage_pos self.box_pos = box_pos self.type = type self.x = x self.y = y self.add(self.color) if self.type == 'center': self.middle_black = CEllipse( texture=CoreImage('images/play.png').texture) else: self.middle_black = CEllipse(cpos=self.storage_pos, csize=(self.size, self.size)) self.add(self.middle_black) self.is_draggable = False self.in_music_box = False
def __init__(self, norm, pos, tempo, clock, tempo_map, touch_points, block_handler): super(TempoCursor, self).__init__() self.norm = norm self.pos = pos self.size = self.norm.nt((70, 70)) self.cursor = CEllipse(cpos=pos, csize=self.size) self.add(Color(1, 1, 1)) self.add(self.cursor) self.tempo = tempo self.clock = clock self.tempo_map = tempo_map self.sched = Scheduler(self.clock, self.tempo_map) self.block_handler = block_handler # 0..15, for 16th note granularity self.touch_points = touch_points self.index = 0 # add touch markers self.add(PushMatrix()) self.add(Translate(*pos)) for touch_point in self.touch_points: self.add(Rotate(angle=-360 * touch_point / 16)) self.add(Color(159 / 255, 187 / 255, 208 / 255)) # blue self.add(Line(points=(0, 0, 0, self.norm.nv(25)), width=2)) self.add(Rotate(angle=360 * touch_point / 16)) self.add(PopMatrix()) # add current time marker self.add(PushMatrix()) self.add(Translate(*pos)) self.time_marker = Line(points=(0, 0, 0, self.norm.nv(30)), width=3) self.rotate = Rotate(angle=0) self.add(self.rotate) self.add(Color(0, 0, 0)) self.add(self.time_marker) self.add(PopMatrix()) self.on_update(0) cur_tick = self.sched.get_tick() next_tick = quantize_tick_up(cur_tick, kTicksPerQuarter * 4) next_tick += self.calculate_tick_interval(0, self.touch_points[0]) self.sched.post_at_tick(self.touch_down, next_tick)
def __init__(self, size = (150,100), pos = (200,200), mode='push', border_color=border_color, active_color=active_color, on_color=on_color, texture=None): super(SensorButton, self).__init__() # button mode self.mode = mode self.texture = texture self.border_color = border_color self.active_color = active_color self.on_color = on_color # button state self.is_on = False self.active_progress = 0 # bounds of this button, for intersection detection self.x_bounds = (pos[0], pos[0] + size[0]) self.y_bounds = (pos[1], pos[1] + size[1]) # inside rectangle coordinates margin = int(.05 * size[0]) self.size2 = np.array(size) - margin self.pos2 = np.array(pos) + 0.5*margin # inside part half_m = int(margin/2) self.inside_color = Color(rgba=self.active_color) self.add( self.inside_color ) self.inside_circle = CEllipse(cpos = (pos[0]+half_m+(size[0]-margin)/2, pos[1]+half_m + (size[1]-margin)/2), csize = (size[0]-margin, size[1]-margin), angle_end=0) self.add( self.inside_circle ) # icon if photo_editor.DARK_MODE: self.add(Color(rgba=(1,1,1,0.95))) else: self.add(Color(rgba=(0,0,0,0.95))) self.texture_rect = Rectangle(size = (self.size2[0]*0.7, self.size2[1]*0.7), pos = (self.pos2[0] + self.size2[0]*0.15, self.pos2[1] + self.size2[1]*0.15), texture = self.texture) self.add( self.texture_rect ) # border of button self.add( Color(rgba=self.border_color) ) self.border = Line(circle = (pos[0]+half_m+(size[0]-margin)/2, pos[1]+half_m + (size[1]-margin)/2, (size[0]-margin)/2 ), width=half_m) self.add(self.border)
def __init__(self): super(Switch, self).__init__() self.on = False dim_size = min(0.05 * Window.width, 0.05 * Window.height) self.line = Line() self.switch_knob = CEllipse() self.add(self.line) self.add(Color(rgb=(235 / 255, 74 / 255, 90 / 255))) self.add(self.switch_knob) self.add(Color(rgb=(1, 1, 1))) img = ImageOps.invert(Image.open('./dominoes/5-7.png').convert('RGB')) data = BytesIO() img.save(data, format='png') data.seek(0) self.white_domino = Rectangle( texture=CoreImage(BytesIO(data.read()), ext='png').texture) self.black_domino = Rectangle( texture=CoreImage('./dominoes/5-7.png').texture) self.add(self.white_domino) self.add(self.black_domino)
class Gear(InstructionGroup): def __init__(self, x, y, size, num_teeth, gear_type, gear_value, storage_pos, box_pos, gear_id, background_color=Color(0, 0, 0), part=0): super(Gear, self).__init__() # part is 0 for melody and 1 for bassline self.part = part self.type = gear_type # 'volume', 'pitch', 'speed', 'instrument', 'center' self.color = self._get_color() self.value = gear_value self.x = x self.y = y self.storage_pos = storage_pos self.box_pos = box_pos self.gear_id = gear_id self.size = size self.add(self.color) self.main_circle = CEllipse(cpos=self.storage_pos, csize=(self.size, self.size)) self.add(self.main_circle) self.middle_size = self.size / 2 self.teeth = [] self.num_teeth = num_teeth self.add_teeth(self.storage_pos, self.num_teeth) self.is_draggable = False self.in_music_box = False self.touch_x_diff = None self.touch_y_diff = None self.time = 0 self.rpm = 0.1 self.is_rotating = False def update_music_pos(self, pos): self.box_pos = pos def update_storage_pos(self, pos): self.storage_pos = pos def _get_color(self): if self.type == 'volume': return colors["red"] elif self.type == 'pitch': return colors["orange"] elif self.type == 'tempo': return colors["purple"] elif self.type == 'center': return Color(rgb=hex_to_rgb('#5e6f81')) elif self.type == 'center1': return colors["trout"] else: return colors["yellow"] def add_teeth(self, center, num_teeth): for tooth in self.teeth: self.remove(tooth) self.teeth = [] self.add(self.color) self.add(PushMatrix()) self.add(Translate(center)) # use this Rotate to animate rotation for the whole flower self.rot = Rotate(angle=0, origin=self.storage_pos) self.add(self.rot) # make petals ellipses with these width and height: self.middle_size = self.size / 2 w = self.size / 5 h = self.size / 5 # how much to rotate each petal. d_theta = 360. / num_teeth for n in range(num_teeth): self.add(Rotate(angle=d_theta, origin=center)) self.add(Translate(self.middle_size, 0)) rect = CRectangle(cpos=center, csize=(h, w)) self.teeth.append(rect) self.add(rect) self.add(Translate(-self.middle_size, 0)) self.add(PopMatrix()) def on_layout(self, pos, size): self.size = size if self.in_music_box: self._update_graphics(self.box_pos) self.rot.origin = self.box_pos else: self._update_graphics(pos) self.rot.origin = pos self.main_circle.set_csize((size, size)) def stop(self): self.is_rotating = False def toggle_rotate(self): self.is_rotating = not self.is_rotating return self.is_rotating def _update_graphics(self, position): self.main_circle.set_cpos(position) self.add_teeth(position, self.num_teeth) def reset(self): self._update_graphics(self.storage_pos) self.rot.origin = self.storage_pos self.in_music_box = False def get_distance_from_center(self, touch): return sqrt((touch[0] - self.main_circle.get_cpos()[0])**2 + (touch[1] - self.main_circle.get_cpos()[1])**2) def on_touch_down(self, touch): distance = self.get_distance_from_center(touch) if distance <= self.size / 2 and distance >= self.middle_size / 2: self.is_draggable = True self.touch_x_diff = touch[0] - self.main_circle.get_cpos()[0] self.touch_y_diff = touch[1] - self.main_circle.get_cpos()[1] return True if self.type == 'center' and distance <= self.size: self.is_draggable = True self.touch_x_diff = touch[0] - self.main_circle.get_cpos()[0] self.touch_y_diff = touch[1] - self.main_circle.get_cpos()[1] return True return False def on_touch_up(self, touch, gear_box_x, can_add_gear): # if it was previously dragged, update it to the correct location if self.is_draggable: if touch[0] <= gear_box_x or not can_add_gear(self): self._update_graphics(self.storage_pos) self.rot.origin = self.storage_pos self.in_music_box = False else: self._update_graphics(self.box_pos) self.rot.origin = self.box_pos self.in_music_box = True self.is_draggable = False return self.in_music_box def on_touch_move(self, touch): if self.is_draggable: self._update_graphics( (touch[0] - self.touch_x_diff, touch[1] - self.touch_y_diff)) self.rot.origin = (touch[0] - self.touch_x_diff, touch[1] - self.touch_y_diff) return True return False def on_update(self, dt, multiple=False): if not multiple: if self.type == 'center': direction = -1 else: direction = 1 else: if self.type == 'center': direction = -1 elif self.type == 'center1': direction = 1 else: direction = -1 if self.is_rotating: degrees_per_sec = self.rpm * 360 / 60 self.rot.angle = degrees_per_sec * self.time self.time += direction * dt
class GearCenter(InstructionGroup): def __init__(self, x, y, storage_pos, box_pos, type, size, background_color): super(GearCenter, self).__init__() self.color = background_color self.size = size self.storage_pos = storage_pos self.box_pos = box_pos self.type = type self.x = x self.y = y self.add(self.color) if self.type == 'center': self.middle_black = CEllipse( texture=CoreImage('images/play.png').texture) else: self.middle_black = CEllipse(cpos=self.storage_pos, csize=(self.size, self.size)) self.add(self.middle_black) self.is_draggable = False self.in_music_box = False def update_music_pos(self, pos): self.box_pos = pos def update_storage_pos(self, pos): self.storage_pos = pos def reset(self): self.middle_black.set_cpos(self.storage_pos) self.in_music_box = False def on_layout(self, pos, size): if self.in_music_box: self.middle_black.set_cpos(self.box_pos) else: self.middle_black.set_cpos(pos) self.middle_black.set_csize((size, size)) def get_distance_from_center(self, touch): return sqrt((touch[0] - self.middle_black.get_cpos()[0])**2 + (touch[1] - self.middle_black.get_cpos()[1])**2) def on_touch_down(self, touch): distance = self.get_distance_from_center(touch) if distance <= self.size and distance >= self.size / 2: self.is_draggable = True self.touch_x_diff = touch[0] - self.middle_black.get_cpos()[0] self.touch_y_diff = touch[1] - self.middle_black.get_cpos()[1] return True return False def on_touch_up(self, touch, gear_box_x, can_add_gear): # if it was previously dragged, update it to the correct location if self.is_draggable: if touch[0] <= gear_box_x or not can_add_gear(self): self.middle_black.set_cpos(self.storage_pos) self.in_music_box = False else: self.middle_black.set_cpos(self.box_pos) self.in_music_box = True self.is_draggable = False return self.in_music_box def on_touch_move(self, touch): if self.is_draggable: self.middle_black.set_cpos( (touch[0] - self.touch_x_diff, touch[1] - self.touch_y_diff)) return True return False
class TimedCEllipse(InstructionGroup): def __init__(self, cpos, radius, texture=None): super(TimedCEllipse, self).__init__() # save position self.cpos = cpos self.r = radius self.width = radius * .2 # code for creating the Line self.rcolor = Color(*kGemRingColor, mode="rgba") self.rrgb = kGemRingColor PushMatrix() self.add(self.rcolor) self.angle = 0 self.ring = Line(circle=(*self.cpos, self.r, self.angle, 360), width=self.width, cap='none') self.add(self.ring) # code for creating the circle self.ccolor = Color(*kGemCircleColor) self.add(self.ccolor) csize = (2 * radius - self.width, ) * 2 self.circ = CEllipse(cpos=cpos, csize=csize) self.add(self.circ) PopMatrix() def set_cpos(self, cpos): '''Set the centered position of the shape''' self.cpos = cpos self.circ.set_cpos(cpos) self.ring.circle = (*cpos, self.r, self.angle, 360) def get_cpos(self): '''Returned centered position of the shape''' return self.cpos def set_radius(self, r): '''Set radius of the shape''' self.r = r self.ring.circle = (*self.cpos, self.r, self.angle, 360) self.width = self.r * .2 self.ring.width = self.width csize = (2 * r - self.width, ) * 2 self.circ.csize = csize def set_ring_color(self, color): '''Set the ring color to indicate correct/incorrect input''' self.rrgb = color self.rcolor.rgba = color def set_alpha(self, a): '''Set the alpha for the sake of animating off the screen''' self.rcolor.a = a self.ccolor.a = a def set_angle(self, angle): '''Set the new angle of the ring''' self.angle = angle self.rcolor.rgba = self.rrgb self.ring.circle = (*self.cpos, self.r, self.angle, 360) def get_angle(self): '''Get the current angle of the ring''' return self.angle
def __init__(self, sm, **kwargs): super(PhotoEditor, self).__init__(**kwargs) # start speech recognition thread threading.Thread(target=speech.speech_main, args=(self, )).start() self.sm = sm # initialize image object self.picture = Picture(filepath) self.canvas.add(self.picture) # create slider group self.slider_group = AnimGroup() self.canvas.add(self.slider_group) # initialize slider self.slider = Slider(1.0, 0, 4) self.slider_line = Line(points=[ 0.98 * Window.width, 0.02 * Window.height, 0.98 * Window.width, 0.98 * Window.height ], width=10) self.slider_group.add(self.slider_line) dim_size = min(0.03 * Window.width, 0.03 * Window.height) self.canvas.add(Color(rgb=(136 / 255, 195 / 255, 0))) self.slider_knob = CEllipse(cpos=(0.98 * Window.width, 0.02 * Window.height), csize=(dim_size, dim_size)) self.slider_group.add(self.slider_knob) # create overlay (4 rectangles within overlay class to mimic crop frame) self.overlay = Overlay(0, 0, 0, 0, self.picture.rectangle.size, self.picture.rectangle.pos) self.canvas.add(self.overlay) # current modification self.mode; possible options are: # - None: no self.mode selected # - 'brightness' : change brightness using slider # - 'contrast' : change contrast using slider # - 'zoom' : makes photo bigger / smaller # - 'crop' : change size of photo self.modes = [ 'save', 'redo', 'undo', 'sticker', 'pixelate', 'invert', 'grayscale', 'transparent', 'saturation', 'sharpness', 'brightness', 'contrast', 'rotate', 'zoom', 'crop' ] self.slider_modes = [ 'brightness', 'contrast', 'saturation', 'sharpness' ] self.mode = None self.mode_instructions = { # we only have instructions for modes that you enter, modes that are applied as soon as the mode's voice command is said are omitted 'crop' : '[font=./fonts/Cairo-Bold]Crop Instructions: [/font][font=./fonts/Cairo-Regular] Use one or two hands; Start with hand(s) outside of the image and move your hand\ntowards the screen until the cursor(s) turns green. Then, move your hands left/right/up/down in toward the picture\nuntil you are happy with the crop. Finally, pull your hand(s) away from the screen until the cursor(s) turn yellow.[/font]', 'zoom' : '[font=./fonts/Cairo-Bold]Zoom Instructions: [/font][font=./fonts/Cairo-Regular] Move two hands towards the screen until both cursors turns green, then move\nthem horizontally/vertically towards or away from each other to zoom out or zoom in. When you are satified,\npull both hands away from the screen until the cursors turn yellow.\n\nTo zoom using your voice, say "in" to zoom in, and "out" to zoom out.[/font]', 'rotate' : '[font=./fonts/Cairo-Bold]Rotate Instructions: [/font][font=./fonts/Cairo-Regular] Move one hand towards the screen until the cursor turns green, then rotate your hand as if you were\nturning a knob so that your fingers face left/right. The picture will rotate 90º in the direction of your fingers.\n\nTo rotate the picture using your voice, say "rotate" and the picture will rotate 90º counterclockwise.[/font]', 'contrast' : '[font=./fonts/Cairo-Bold]Contrast Instructions: [/font][font=./fonts/Cairo-Regular] Move one hand towards the screen until the cursor turns green, then move your hand up/down to\nincrease/decrease the contrast. When you are satified, pull your hand away from the screen until the cursor turns yellow.\n\nTo change the contrast using your voice, say "increase" (or a synonym) to increase the contrast, and "decrease" (or a\nsynonym) to decrease the contrast.[/font]', 'brightness' : '[font=./fonts/Cairo-Bold]Brightness Instructions: [/font][font=./fonts/Cairo-Regular] Move one hand towards the screen until the cursor turns green, then move your hand up/down to\nincrease/decrease the brightness. When you are satified, pull your hand away from the screen until the cursor turns yellow.\n\nTo change the brightness using your voice, say "increase" (or a synonym) to increase the brightness, and "decrease" (or a\nsynonym)to decrease the brightness.[/font]', 'sharpness' : '[font=./fonts/Cairo-Bold]Sharpness Instructions: [/font][font=./fonts/Cairo-Regular] Move one hand towards the screen until the cursor turns green, then move your hand up/down to\nincrease/decrease the sharpness. When you are satified, pull your hand away from the screen until the cursor turns yellow.\n\nTo change the sharpness using your voice, say "increase" (or a synonym) to increase the sharpness, and "decrease" (or a\nsynonym)to decrease the sharpness.[/font]', 'saturation' : '[font=./fonts/Cairo-Bold]Saturation Instructions: [/font][font=./fonts/Cairo-Regular] Move one hand towards the screen until the cursor turns green, then move your hand up/down to\nincrease/decrease the saturation. When you are satified, pull your hand away from the screen until the cursor turns yellow.\n\nTo change the saturation using your voice, say "increase" (or a synonym) to increase the saturation, and "decrease" (or a\nsynonym)to decrease the saturation.[/font]', 'pixelate' : '[font=./fonts/Cairo-Bold]Pixelate Instructions: [/font][font=./fonts/Cairo-Regular] To increase the pixelation of the image by voice, say "increase" (or a synonym).\nTo return the picture to its original state, say "undo." [/font]', 'sticker' : '[font=./fonts/Cairo-Bold]Sticker Instructions: [/font][font=./fonts/Cairo-Regular] View the names of the stickers on the bottom of the screen by hovering over them. Then, hover\nover the part of the image where you want to place the sticker and say the name of the sticker you want to apply.[/font]', 'transparent' : '[font=./fonts/Cairo-Bold]Transparent Instructions: [/font][font=./fonts/Cairo-Regular] Hover over the area you wish to make transparent and say "apply". You can also modify\nthe transparency threshold in settings. To get to the settings page, hover over the gear in the top right corner.[/font]', } self.mode_instructions_label = Label(halign='center', markup=True) self.add_widget(self.mode_instructions_label) # add icon bar on left_hand side self.icon_label = Label() self.icon_bar = IconBar(self.modes, self.icon_label) self.canvas.add(self.icon_bar) self.add_widget(self.icon_label) # sticker bar self.sticker_label = Label() self.sticker_bar = StickerBar(self.sticker_label) self.add_widget(self.sticker_label) # settings button self.settings_button = SensorButton( size=(Window.width / 15, Window.width / 15), pos=(0.97 * Window.width - Window.width / 15, 0.98 * Window.height - Window.width / 15), mode='hover', texture=CoreImage('icons/settings.png').texture) self.canvas.add(self.settings_button) # menu button self.menu_button = SensorButton( size=(Window.width / 15, Window.width / 15), pos=(0.96 * Window.width - 2 * Window.width / 15, 0.98 * Window.height - Window.width / 15), mode='hover', texture=CoreImage('icons/menu.png').texture) self.canvas.add(self.menu_button) self.switch_to_timer = None # Hand objects that represent and show palm positions self.hands = [Hand(1), Hand(2)] for h in self.hands: self.canvas.add(h)
class NowBar(InstructionGroup): def __init__(self, bpm): super(NowBar, self).__init__() self.bpm = bpm # color the cursor grey self.color = Color(*kCursorDefaultColor) self.add(self.color) # save position and size self.xpos = PlaceOnBeat(.75) #kTrackLowerLimit self.xstart = self.xpos self.ypos = kGemBarYPos self.csize = kCursorSize # draw the cursor as a circle cpos = (self.xpos, self.ypos) self.cursor = CEllipse(cpos=cpos, csize=self.csize, texture=Image(kNowBarPng).texture) self.add(self.cursor) # limits that NowBar will be moving within, correlates with length of gem bar self.lim_lo = kTrackLowerLimit self.lim_hi = Window.width - self.lim_lo # save time for animation, by starting large, the cursor will maintain its size self.t = kCursorMaxTime # save speed of the cursor self.v = BpmToPixels(bpm) # initialize position of the NowBar self.active = True # hold callback that will be used to indicate reaching the end of the line self.end_cb = None def install_cb(self, cb): self.end_cb = cb def change_bpm(self, bpm): self.bpm = bpm self.v = BpmToPixels(self.bpm) def get_xpos(self): return self.xpos def update_pos(self, dt): # y should remain constant curr_xpos = self.cursor.get_cpos()[0] new_xpos = curr_xpos + self.v * dt self.cursor.set_cpos((new_xpos, self.ypos)) if not self.in_bounds(): if self.end_cb: self.end_cb() self.reset() self.xpos = self.cursor.get_cpos()[0] # move cursor back to beginning of the screen def reset(self): self.cursor.set_cpos((self.lim_lo, self.ypos)) def restart(self): self.cursor.set_cpos((self.xstart, self.ypos)) self.activate(True) # animate def animate(self, dt): new_size = kCursorSize[0] * exp(-kCursorDecayRate * self.t) * cos( kCursorOscRate * self.t) + kCursorSize[0] self.csize = (new_size, new_size) self.cursor.csize = self.csize self.t = kCursorMaxTime if ( self.t + dt >= kCursorMaxTime) else self.t + dt # reset time for animating key presses, can call this function when input is recorded def time_reset(self): self.t = 0 # find out if the barline is on screen, if so we will draw it def in_bounds(self): xpos = self.cursor.get_cpos()[0] return True if self.lim_lo <= xpos <= self.lim_hi else False def activate(self, active): self.active = active # update position and update animation def on_update(self, dt): # return whether the bar is active or inactive self.update_pos(dt) self.animate(dt) return self.active