class IcarusTouchWidget(Widget): app = ObjectProperty(None) float_layout = ObjectProperty(None) pitch_lock_button = ObjectProperty(None) y_axis_volume_button = ObjectProperty(None) setting_button = ObjectProperty(None) look_button = ObjectProperty(None) feedback_wall = ObjectProperty(None) scale_keywidth_touch_positions = {} version = StringProperty(VERSION) ''' #################################### ## ## Class Initialisation ## #################################### ''' def __init__(self, **kwargs): super(IcarusTouchWidget, self).__init__(**kwargs) # don't know if this is necessary? # add background image (and add it in the BACKGROUND! --> index modification) self.background = Background( source=self.app.config.get('Graphics', 'Background')) self.float_layout.add_widget(self.background, index=len(self.float_layout.children)) # add feedback wall image self.feedback_wall = Feedback(source='images/feedbackwall.png', transparency=0) self.float_layout.add_widget(self.feedback_wall) # add the keyboard itself my_key_width = KEY_WIDTH self.keyboard = Keyboard( source=self.app.config.get('Graphics', 'Keyboard'), pos=(-540, 366), size=( 12 * 5 * my_key_width, 468 ), # optimization for small screens (e.g. smartphones): 468 if self.get_parent_window().height > (468 + self.get_parent_window().height * 0.3) else self.get_parent_window().height * 0.7 border_width=BORDER_WIDTH, key_width=my_key_width) self.add_widget(self.keyboard) # initialize the midi device pygame.midi.init() self.set_midi_device() # initialize the settings_panel (I'm doing this here, otherwise opening it in real-time takes ages...) self.my_settings_panel = MySettingsPanel() ''' #################################### ## ## On Touch Down ## #################################### ''' def on_touch_down(self, touch): ud = touch.ud # find out the touchs "function": if self.my_settings_panel.is_open == True: # if the settingspanel is opened, it has total focus! # so if the user clicked on one of the two panels, don't dispatch the touch here but feed it to the panel if self.my_settings_panel.keyboard_scroll_view_box.collide_point(*touch.pos) or \ self.my_settings_panel.background_scroll_view_grid.collide_point(*touch.pos): ud['settingspanel'] = True return super(IcarusTouchWidget, self).on_touch_down(touch) else: # user has clicked aside - he wants to quit the settings. self.close_my_settings_panel() return True elif self.keyboard.collide_point(*touch.pos): # if the user touched on the keyboard, feed the touch to the keyboard. return super(IcarusTouchWidget, self).on_touch_down(touch) elif self.pitch_lock_button.collide_point(*touch.pos) or \ self.y_axis_volume_button.collide_point(*touch.pos) or \ self.look_button.collide_point(*touch.pos) or \ self.settings_button.collide_point(*touch.pos): # if the user touched one of the buttons, feed the touch to the buttons self.create_circle(touch) return super(IcarusTouchWidget, self).on_touch_down(touch) ########################## # X-Axis Key width scaling ########################## ''' # if it wasn't a button nor a key touch nor a settings touch, its a scroll touch. for search_touch in EventLoop.touches[:]: # but if there is already another touch in scroll mode (and not already in 'scale' mode), maybe the desired action is 'scale' not 'scroll' if 'scroll' in search_touch.ud and not self.scale_keywidth_touch_positions: # remember their actual positions self.scale_keywidth_touch_positions = {'initial_first': search_touch.x, 'initial_second': touch.x, 'first_touch': search_touch, 'second_touch': touch} print 'multiple saving position data' ''' # assign the scroll-tag not until here. Thus we just get the other existing scroll-touches in the search-routine above. ud['scroll'] = True # if there was an keyboard "spring back" animation in progress, stop it. self.keyboard.keyboard_x_animation.stop(self.keyboard) ''' #################################### ## ## On Touch Move ## #################################### ''' def on_touch_move(self, touch): ud = touch.ud ########################## # X-Axis Key width scaling ########################## ''' # if there are two fingers in scroll mode (thus the user dictionary key 'scale_keywidth_touch_positions' isn't empty) - maybe he wants to scale the keywidth? scalepos = self.scale_keywidth_touch_positions if scalepos: delta_first_touch = scalepos['first_touch'].x - scalepos['initial_first'] delta_second_touch = scalepos['second_touch'].x - scalepos['initial_second'] #print 'move: delta_first = %s, delta_second = %s' % (delta_first_touch, delta_second_touch) # if the user dragged both touches towards each other or vice versa if (delta_first_touch > SCALE_KEYWIDTH_THRESHOLD and delta_second_touch > -SCALE_KEYWIDTH_THRESHOLD) or \ (delta_first_touch > -SCALE_KEYWIDTH_THRESHOLD and delta_second_touch > SCALE_KEYWIDTH_THRESHOLD): print 'scale mode!' # if the first touch was on the left and the user moved it right OR it was right and moved to the left, we want to make the keywidth smaller if (scalepos['initial_first'] < scalepos['initial_second'] and delta_first_touch > 0) or \ (scalepos['initial_first'] > scalepos['initial_second'] and delta_first_touch < 0): print 'zoom out' # perform a ZOOM OUT with a factor applied to the delta_touch_distance: delta_touch_distance = abs(delta_first_touch + (-delta_second_touch)) self.keyboard.key_width -= int(delta_touch_distance / SCALE_KEYWIDTH_FACTOR) self.keyboard.width = 12*5*self.keyboard.key_width # if the first touch was on the left and the user moved it left OR it was right and moved to the right, we want to make the keywidth smaller elif (scalepos['initial_first'] < scalepos['initial_second'] and delta_first_touch < 0) or \ (scalepos['initial_first'] > scalepos['initial_second'] and delta_first_touch > 0): print 'zoom in' # perform a ZOOM IN in with a factor applied to the delta_touch_distance: delta_touch_distance = abs(delta_first_touch + (-delta_second_touch)) self.keyboard.key_width += int(delta_touch_distance / SCALE_KEYWIDTH_FACTOR) self.keyboard.width = 12*5*self.keyboard.key_width ''' if 'scroll' in ud: # move keyboard left or right. # nice side effect: if there is more than 1 touch in 'scroll' mode, scrolling is faster! scroll_factor = 1 # if the end of the keyboard is visible, scroll slower! if self.keyboard.x > 0 or self.keyboard.x < ( self.get_parent_window().width - self.keyboard.width): counter = 0 for touch in EventLoop.touches[:]: if 'scroll' in touch.ud: counter += 1 # how many touches are in 'scroll' mode? # if there is more than one touch in scroll mode, i don't want the factor to grow! scroll_factor = SCROLLING_STICKY_FACTOR / counter # apply the scroll action self.keyboard.x += touch.dx * scroll_factor return # if the touch was started on the keyboard if 'initial_key' in ud or 'settingspanel' in ud: return super(IcarusTouchWidget, self).on_touch_move(touch) ''' #################################### ## ## On Touch Up ## #################################### ''' def on_touch_up(self, touch): ud = touch.ud #@@@@@@@@@@@@@@@@ # Scroll Touch #@@@@@@@@@@@@@@@@ # if there has been scale mode active or perhaps happening: (better would be: "and there aren't multiple 'scroll' mode touches active anymore if self.scale_keywidth_touch_positions: # delete all scale mode variables #print 'deleting the position data' self.scale_keywidth_touch_positions = {} if 'scroll' in ud: win = self.get_parent_window() # if keyboard end is visible and the touch is released, "jump" on old place: if self.keyboard.x > 0: self.keyboard.keyboard_x_animation = Animation( x=0, t='out_cubic', duration=KEYBOARD_ANIMATION_X_DURATION) self.keyboard.keyboard_x_animation.start(self.keyboard) elif self.keyboard.x < (win.width - self.keyboard.width): self.keyboard.keyboard_x_animation = Animation( x=win.width - self.keyboard.width, t='out_cubic', duration=KEYBOARD_ANIMATION_X_DURATION) self.keyboard.keyboard_x_animation.start(self.keyboard) if 'initial_key' in ud: return super(IcarusTouchWidget, self).on_touch_up(touch) ''' #################################### ## ## Other GUI Events ## #################################### ''' def on_y_axis_volume_button_press(self): # apply the visible button-state also to the application settings if self.y_axis_volume_button.state == 'down': # Y axis => volume self.app.config.set('General', 'YAxis', 'Volume') # lock aftertouch to 0: self.midi_out.write_short(0xD0, 0) else: # Y axis => aftertouch self.app.config.set('General', 'YAxis', 'Aftertouch') # lock Y-modulation to 127 self.midi_out.write_short(0xB0, 1, 127) self.app.config.write() def on_pitch_lock_button_press(self): # apply the visible button-state also to the application settings if self.pitch_lock_button.state == 'down': self.app.config.set('General', 'PitchLock', 'On') else: self.app.config.set('General', 'PitchLock', 'Off') self.app.config.write() def open_settings(self): # is called from the rightmost button (the "setup" button") --> function call binding in the .kv file self.app.open_settings() ''' #################################### ## ## Graphical Functions ## #################################### ''' def create_circle(self, touch): # create the circle image circle = Image(source=self.app.config.get('Advanced', 'CircleImage'), color=CIRCLE_IMAGE_COLOR, allow_stretch=True, size=(self.app.config.getint('Advanced', 'CircleSize'), self.app.config.getint('Advanced', 'CircleSize'))) # center the circle on the finger position circle.x = touch.x - circle.size[0] / 2 circle.y = touch.y - circle.size[1] / 2 self.add_widget(circle) # and just right fade it out after having displayed it animation = Animation( color=CIRCLE_IMAGE_COLOR_TRANSPARENT, size=(self.app.config.getint('Advanced', 'CircleSize') * 2, self.app.config.getint('Advanced', 'CircleSize') * 2), x=circle.pos[0] - (self.app.config.getint('Advanced', 'CircleSize') / 2), # workaround for centering the image during resizing y=circle.pos[1] - (self.app.config.getint('Advanced', 'CircleSize') / 2), # workaround for centering the image during resizing t='out_expo', duration=CIRCLE_IMAGE_FADEOUT_TIME) animation.start(circle) animation.bind(on_complete=self.circle_fadeout_complete) def circle_fadeout_complete(self, animation, widget): self.remove_widget(widget) ''' #################################### ## ## Settings Functions ## #################################### ''' def set_midi_device(self): # take the midi device of the settings file and try to connect to it. # If there isn't such a device, connect to the default one. c = pygame.midi.get_count() id_device_from_settings = -1 #print '%s midi devices found' % c for i in range(c): #print '%s name: %s input: %s output: %s opened: %s' % (pygame.midi.get_device_info(i)) if pygame.midi.get_device_info(i)[1] == self.app.config.get( 'MIDI', 'Device'): # if the device from the settings exists in the computers list, take that! id_device_from_settings = i #print 'Default is %s' % pygame.midi.get_device_info(pygame.midi.get_default_output_id())[1] if id_device_from_settings <> -1: self.midi_device = id_device_from_settings print 'MIDI device "%s" found. Connecting.' % pygame.midi.get_device_info( id_device_from_settings)[1] else: # if it was not in the list, take the default one self.midi_device = pygame.midi.get_default_output_id() print 'Warning: No MIDI device named "%s" found. Choosing the system default ("%s").' % ( self.app.config.get('MIDI', 'Device'), pygame.midi.get_device_info(self.midi_device)[1]) if pygame.midi.get_device_info(self.midi_device)[4] == 1: print 'Error: Can' 't open the MIDI device - It' 's already opened!' self.midi_out = pygame.midi.Output(self.midi_device) def open_my_settings_panel(self): self.add_widget(self.my_settings_panel) # bind the background images to function for child in self.my_settings_panel.background_scroll_view_grid.children: child.bind(on_press=self.background_image_change_request) # bind the keyboard images to function for child in self.my_settings_panel.keyboard_scroll_view_box.children: child.bind(on_press=self.keyboard_image_change_request) self.my_settings_panel.is_open = True def close_my_settings_panel(self): self.remove_widget(self.my_settings_panel) self.my_settings_panel.is_open = False def background_image_change_request(self, dispatcher): self.background_image_change(dispatcher.background_normal) def keyboard_image_change_request(self, dispatcher): self.keyboard_image_change(dispatcher.background_normal) def background_image_change(self, value): # first set the new background into the application settings: self.app.config.set('Graphics', 'Background', value) self.app.config.write() old_background_instance = self.background # if the last background change is still in progress, stop it and start the new one. if old_background_instance.background_is_animated == True: old_background_instance.new_background_change_animation.stop( old_background_instance.new_background_instance) old_background_instance.old_background_change_animation.stop( old_background_instance) self.float_layout.remove_widget(old_background_instance) old_background_instance.new_background_instance.color = (1, 1, 1, 1) old_background_instance = old_background_instance.new_background_instance # create the new image instance old_background_instance.new_background_instance = Background( source=value, color=(1, 1, 1, 0)) # add the new instance to the root widget. BUT add it on the bottom (therefore I set the index myself) self.float_layout.add_widget( old_background_instance.new_background_instance, index=len(self.float_layout.children)) # keep the settings panel on the front self.remove_widget(self.my_settings_panel) self.add_widget(self.my_settings_panel) # let the old image fade out while the new one fades in. old_background_instance.new_background_change_animation = Animation( color=(1, 1, 1, 1), duration=BACKGROUND_CHANGE_DURATION) old_background_instance.old_background_change_animation = Animation( color=(1, 1, 1, 0), duration=BACKGROUND_CHANGE_DURATION) old_background_instance.new_background_change_animation.start( old_background_instance.new_background_instance) old_background_instance.old_background_change_animation.start( old_background_instance) old_background_instance.background_is_animated = True old_background_instance.new_background_change_animation.bind( on_complete=self.background_change_complete) def background_change_complete(self, animation, widget): # first remove the old background from the widget tree self.remove_widget(self.background) # then make the self.background reference refer to the new background self.background = widget self.background.background_is_animated = False def keyboard_image_change(self, value): # first set the new keyboard into the application settings: self.app.config.set('Graphics', 'Keyboard', value) self.app.config.write() win = self.get_parent_window() old_keyboard_instance = self.keyboard # if the last keyboard change is stil in progress, stop it and start the new. if old_keyboard_instance.keyboard_is_animated == True: old_keyboard_instance.new_keyboard_change_animation.stop( old_keyboard_instance.new_keyboard_instance) old_keyboard_instance.old_keyboard_change_animation.stop( old_keyboard_instance) self.remove_widget(old_keyboard_instance) old_keyboard_instance.new_keyboard_instance.y = 366 old_keyboard_instance = old_keyboard_instance.new_keyboard_instance # create the new image instance old_keyboard_instance.new_keyboard_instance = Keyboard( source=value, pos=(old_keyboard_instance.x, win.height + BORDER_WIDTH), size=(self.keyboard.width, old_keyboard_instance.height), key_width=old_keyboard_instance.key_width, border_width=BORDER_WIDTH) self.add_widget(old_keyboard_instance.new_keyboard_instance) # keep the settings panel on the front self.remove_widget(self.my_settings_panel) self.add_widget(self.my_settings_panel) # let the old image fade out while the new one fades in. old_keyboard_instance.new_keyboard_change_animation = Animation( y=366, t='out_back', duration=KEYBOARD_CHAGE_DURATION) old_keyboard_instance.old_keyboard_change_animation = Animation( y=-(self.keyboard.height + BORDER_WIDTH), t='out_back', duration=KEYBOARD_CHAGE_DURATION) old_keyboard_instance.new_keyboard_change_animation.start( old_keyboard_instance.new_keyboard_instance) old_keyboard_instance.old_keyboard_change_animation.start( old_keyboard_instance) old_keyboard_instance.keyboard_is_animated = True old_keyboard_instance.new_keyboard_change_animation.bind( on_complete=self.keyboard_change_complete) def keyboard_change_complete(self, animation, widget): # first remove the old keyboard from the widget tree self.remove_widget(self.keyboard) # then make the self.keyboard reference refer to the new keyboard self.keyboard = widget self.keyboard.keyboard_is_animated = False
class IcarusTouchWidget(Widget): app = ObjectProperty(None) float_layout = ObjectProperty(None) pitch_lock_button = ObjectProperty(None) y_axis_volume_button = ObjectProperty(None) setting_button = ObjectProperty(None) look_button = ObjectProperty(None) feedback_wall = ObjectProperty(None) scale_keywidth_touch_positions = {} version = StringProperty(VERSION) ''' #################################### ## ## Class Initialisation ## #################################### ''' def __init__(self, **kwargs): super(IcarusTouchWidget, self).__init__(**kwargs) # don't know if this is necessary? # add background image (and add it in the BACKGROUND! --> index modification) self.background = Background(source=self.app.config.get('Graphics', 'Background')) self.float_layout.add_widget(self.background, index=len(self.float_layout.children)) # add feedback wall image self.feedback_wall = Feedback( source='images/feedbackwall.png', transparency=0) self.float_layout.add_widget(self.feedback_wall) # add the keyboard itself my_key_width = KEY_WIDTH self.keyboard = Keyboard( source=self.app.config.get('Graphics', 'Keyboard'), pos=(-540, 230), # 366 size=(12*5*my_key_width, 468), # optimization for small screens (e.g. smartphones): 468 if self.get_parent_window().height > (468 + self.get_parent_window().height * 0.3) else self.get_parent_window().height * 0.7 border_width=BORDER_WIDTH, key_width=my_key_width) self.add_widget(self.keyboard) # initialize the midi device pygame.midi.init() self.set_midi_device() # initialize the settings_panel (I'm doing this here, otherwise opening it in real-time takes ages...) self.my_settings_panel = MySettingsPanel() ''' #################################### ## ## On Touch Down ## #################################### ''' def on_touch_down(self, touch): ud = touch.ud # find out the touchs "function": if self.my_settings_panel.is_open == True: # if the settingspanel is opened, it has total focus! # so if the user clicked on one of the two panels, don't dispatch the touch here but feed it to the panel if self.my_settings_panel.keyboard_scroll_view_box.collide_point(*touch.pos) or \ self.my_settings_panel.background_scroll_view_grid.collide_point(*touch.pos): ud['settingspanel'] = True return super(IcarusTouchWidget, self).on_touch_down(touch) else: # user has clicked aside - he wants to quit the settings. self.close_my_settings_panel() return True elif self.keyboard.collide_point(*touch.pos): # if the user touched on the keyboard, feed the touch to the keyboard. return super(IcarusTouchWidget, self).on_touch_down(touch) elif self.pitch_lock_button.collide_point(*touch.pos) or \ self.y_axis_volume_button.collide_point(*touch.pos) or \ self.look_button.collide_point(*touch.pos) or \ self.settings_button.collide_point(*touch.pos): # if the user touched one of the buttons, feed the touch to the buttons self.create_circle(touch) return super(IcarusTouchWidget, self).on_touch_down(touch) ########################## # X-Axis Key width scaling ########################## ''' # if it wasn't a button nor a key touch nor a settings touch, its a scroll touch. for search_touch in EventLoop.touches[:]: # but if there is already another touch in scroll mode (and not already in 'scale' mode), maybe the desired action is 'scale' not 'scroll' if 'scroll' in search_touch.ud and not self.scale_keywidth_touch_positions: # remember their actual positions self.scale_keywidth_touch_positions = {'initial_first': search_touch.x, 'initial_second': touch.x, 'first_touch': search_touch, 'second_touch': touch} print 'multiple saving position data' ''' # assign the scroll-tag not until here. Thus we just get the other existing scroll-touches in the search-routine above. ud['scroll'] = True # if there was an keyboard "spring back" animation in progress, stop it. self.keyboard.keyboard_x_animation.stop(self.keyboard) ''' #################################### ## ## On Touch Move ## #################################### ''' def on_touch_move(self, touch): ud = touch.ud ########################## # X-Axis Key width scaling ########################## ''' # if there are two fingers in scroll mode (thus the user dictionary key 'scale_keywidth_touch_positions' isn't empty) - maybe he wants to scale the keywidth? scalepos = self.scale_keywidth_touch_positions if scalepos: delta_first_touch = scalepos['first_touch'].x - scalepos['initial_first'] delta_second_touch = scalepos['second_touch'].x - scalepos['initial_second'] #print 'move: delta_first = %s, delta_second = %s' % (delta_first_touch, delta_second_touch) # if the user dragged both touches towards each other or vice versa if (delta_first_touch > SCALE_KEYWIDTH_THRESHOLD and delta_second_touch > -SCALE_KEYWIDTH_THRESHOLD) or \ (delta_first_touch > -SCALE_KEYWIDTH_THRESHOLD and delta_second_touch > SCALE_KEYWIDTH_THRESHOLD): print 'scale mode!' # if the first touch was on the left and the user moved it right OR it was right and moved to the left, we want to make the keywidth smaller if (scalepos['initial_first'] < scalepos['initial_second'] and delta_first_touch > 0) or \ (scalepos['initial_first'] > scalepos['initial_second'] and delta_first_touch < 0): print 'zoom out' # perform a ZOOM OUT with a factor applied to the delta_touch_distance: delta_touch_distance = abs(delta_first_touch + (-delta_second_touch)) self.keyboard.key_width -= int(delta_touch_distance / SCALE_KEYWIDTH_FACTOR) self.keyboard.width = 12*5*self.keyboard.key_width # if the first touch was on the left and the user moved it left OR it was right and moved to the right, we want to make the keywidth smaller elif (scalepos['initial_first'] < scalepos['initial_second'] and delta_first_touch < 0) or \ (scalepos['initial_first'] > scalepos['initial_second'] and delta_first_touch > 0): print 'zoom in' # perform a ZOOM IN in with a factor applied to the delta_touch_distance: delta_touch_distance = abs(delta_first_touch + (-delta_second_touch)) self.keyboard.key_width += int(delta_touch_distance / SCALE_KEYWIDTH_FACTOR) self.keyboard.width = 12*5*self.keyboard.key_width ''' if 'scroll' in ud: # move keyboard left or right. # nice side effect: if there is more than 1 touch in 'scroll' mode, scrolling is faster! scroll_factor = 1 # if the end of the keyboard is visible, scroll slower! if self.keyboard.x > 0 or self.keyboard.x < (self.get_parent_window().width - self.keyboard.width): counter = 0 for touch in EventLoop.touches[:]: if 'scroll' in touch.ud: counter += 1 # how many touches are in 'scroll' mode? # if there is more than one touch in scroll mode, i don't want the factor to grow! scroll_factor = SCROLLING_STICKY_FACTOR / counter # apply the scroll action self.keyboard.x += touch.dx * scroll_factor return # if the touch was started on the keyboard if 'initial_key' in ud or 'settingspanel' in ud: return super(IcarusTouchWidget, self).on_touch_move(touch) ''' #################################### ## ## On Touch Up ## #################################### ''' def on_touch_up(self, touch): ud = touch.ud #@@@@@@@@@@@@@@@@ # Scroll Touch #@@@@@@@@@@@@@@@@ # if there has been scale mode active or perhaps happening: (better would be: "and there aren't multiple 'scroll' mode touches active anymore if self.scale_keywidth_touch_positions: # delete all scale mode variables #print 'deleting the position data' self.scale_keywidth_touch_positions = {} if 'scroll' in ud: win = self.get_parent_window() # if keyboard end is visible and the touch is released, "jump" on old place: if self.keyboard.x > 0: self.keyboard.keyboard_x_animation = Animation(x=0, t='out_cubic', duration=KEYBOARD_ANIMATION_X_DURATION) self.keyboard.keyboard_x_animation.start(self.keyboard) elif self.keyboard.x < (win.width - self.keyboard.width): self.keyboard.keyboard_x_animation = Animation(x=win.width - self.keyboard.width, t='out_cubic', duration=KEYBOARD_ANIMATION_X_DURATION) self.keyboard.keyboard_x_animation.start(self.keyboard) if 'initial_key' in ud: return super(IcarusTouchWidget, self).on_touch_up(touch) ''' #################################### ## ## Other GUI Events ## #################################### ''' def on_y_axis_volume_button_press(self): # apply the visible button-state also to the application settings if self.y_axis_volume_button.state == 'down': # Y axis => volume self.app.config.set('General', 'YAxis', 'Volume') # lock aftertouch to 0: self.midi_out.write_short(0xD0, 0) else: # Y axis => aftertouch self.app.config.set('General', 'YAxis', 'Aftertouch') # lock Y-modulation to 127 self.midi_out.write_short(0xB0, 1, 127) self.app.config.write() def on_pitch_lock_button_press(self): # apply the visible button-state also to the application settings if self.pitch_lock_button.state == 'down': self.app.config.set('General', 'PitchLock', 'On') else: self.app.config.set('General', 'PitchLock', 'Off') self.app.config.write() def open_settings(self): # is called from the rightmost button (the "setup" button") --> function call binding in the .kv file self.app.open_settings() ''' #################################### ## ## Graphical Functions ## #################################### ''' def create_circle(self, touch): # create the circle image circle = Image( source=self.app.config.get('Advanced', 'CircleImage'), color=CIRCLE_IMAGE_COLOR, allow_stretch=True, size=(self.app.config.getint('Advanced', 'CircleSize'), self.app.config.getint('Advanced', 'CircleSize'))) # center the circle on the finger position circle.x = touch.x - circle.size[0] / 2 circle.y = touch.y - circle.size[1] / 2 self.add_widget(circle) # and just right fade it out after having displayed it animation = Animation( color=CIRCLE_IMAGE_COLOR_TRANSPARENT, size=(self.app.config.getint('Advanced', 'CircleSize') * 2, self.app.config.getint('Advanced', 'CircleSize') * 2), x=circle.pos[0] - (self.app.config.getint('Advanced', 'CircleSize')/2), # workaround for centering the image during resizing y=circle.pos[1] - (self.app.config.getint('Advanced', 'CircleSize')/2), # workaround for centering the image during resizing t='out_expo', duration=CIRCLE_IMAGE_FADEOUT_TIME) animation.start(circle) animation.bind(on_complete=self.circle_fadeout_complete) def circle_fadeout_complete(self, animation, widget): self.remove_widget(widget) ''' #################################### ## ## Settings Functions ## #################################### ''' def set_midi_device(self): # take the midi device of the settings file and try to connect to it. # If there isn't such a device, connect to the default one. c = pygame.midi.get_count() id_device_from_settings = -1 #print '%s midi devices found' % c for i in range(c): #print '%s name: %s input: %s output: %s opened: %s' % (pygame.midi.get_device_info(i)) if pygame.midi.get_device_info(i)[1] == self.app.config.get('MIDI', 'Device'): # if the device from the settings exists in the computers list, take that! id_device_from_settings = i #print 'Default is %s' % pygame.midi.get_device_info(pygame.midi.get_default_output_id())[1] if id_device_from_settings <> -1: self.midi_device = id_device_from_settings print 'MIDI device "%s" found. Connecting.' % pygame.midi.get_device_info(id_device_from_settings)[1] else: # if it was not in the list, take the default one self.midi_device = pygame.midi.get_default_output_id() print 'Warning: No MIDI device named "%s" found. Choosing the system default ("%s").' % (self.app.config.get('MIDI', 'Device'), pygame.midi.get_device_info(self.midi_device)[1]) if pygame.midi.get_device_info(self.midi_device)[4] == 1: print 'Error: Can''t open the MIDI device - It''s already opened!' self.midi_out = pygame.midi.Output(self.midi_device) def open_my_settings_panel(self): self.add_widget(self.my_settings_panel) # bind the background images to function for child in self.my_settings_panel.background_scroll_view_grid.children: child.bind(on_press=self.background_image_change_request) # bind the keyboard images to function for child in self.my_settings_panel.keyboard_scroll_view_box.children: child.bind(on_press=self.keyboard_image_change_request) self.my_settings_panel.is_open = True def close_my_settings_panel(self): self.remove_widget(self.my_settings_panel) self.my_settings_panel.is_open = False def background_image_change_request(self, dispatcher): self.background_image_change(dispatcher.background_normal) def keyboard_image_change_request(self, dispatcher): self.keyboard_image_change(dispatcher.background_normal) def background_image_change(self, value): # first set the new background into the application settings: self.app.config.set('Graphics', 'Background', value) self.app.config.write() old_background_instance = self.background # if the last background change is still in progress, stop it and start the new one. if old_background_instance.background_is_animated == True: old_background_instance.new_background_change_animation.stop(old_background_instance.new_background_instance) old_background_instance.old_background_change_animation.stop(old_background_instance) self.float_layout.remove_widget(old_background_instance) old_background_instance.new_background_instance.color = (1, 1, 1, 1) old_background_instance = old_background_instance.new_background_instance # create the new image instance old_background_instance.new_background_instance = Background( source=value, color=(1, 1, 1, 0)) # add the new instance to the root widget. BUT add it on the bottom (therefore I set the index myself) self.float_layout.add_widget(old_background_instance.new_background_instance, index=len(self.float_layout.children)) # keep the settings panel on the front self.remove_widget(self.my_settings_panel) self.add_widget(self.my_settings_panel) # let the old image fade out while the new one fades in. old_background_instance.new_background_change_animation = Animation(color=(1, 1, 1, 1), duration=BACKGROUND_CHANGE_DURATION) old_background_instance.old_background_change_animation = Animation(color=(1, 1, 1, 0), duration=BACKGROUND_CHANGE_DURATION) old_background_instance.new_background_change_animation.start(old_background_instance.new_background_instance) old_background_instance.old_background_change_animation.start(old_background_instance) old_background_instance.background_is_animated = True old_background_instance.new_background_change_animation.bind(on_complete=self.background_change_complete) def background_change_complete(self, animation, widget): # first remove the old background from the widget tree self.remove_widget(self.background) # then make the self.background reference refer to the new background self.background = widget self.background.background_is_animated = False def keyboard_image_change(self, value): # first set the new keyboard into the application settings: self.app.config.set('Graphics', 'Keyboard', value) self.app.config.write() win = self.get_parent_window() old_keyboard_instance = self.keyboard # if the last keyboard change is stil in progress, stop it and start the new. if old_keyboard_instance.keyboard_is_animated == True: old_keyboard_instance.new_keyboard_change_animation.stop(old_keyboard_instance.new_keyboard_instance) old_keyboard_instance.old_keyboard_change_animation.stop(old_keyboard_instance) self.remove_widget(old_keyboard_instance) old_keyboard_instance.new_keyboard_instance.y = 366 old_keyboard_instance = old_keyboard_instance.new_keyboard_instance # create the new image instance old_keyboard_instance.new_keyboard_instance = Keyboard( source=value, pos=(old_keyboard_instance.x, win.height + BORDER_WIDTH), size=(self.keyboard.width, old_keyboard_instance.height), key_width=old_keyboard_instance.key_width, border_width=BORDER_WIDTH) self.add_widget(old_keyboard_instance.new_keyboard_instance) # keep the settings panel on the front self.remove_widget(self.my_settings_panel) self.add_widget(self.my_settings_panel) # let the old image fade out while the new one fades in. old_keyboard_instance.new_keyboard_change_animation = Animation(y=366, t='out_back', duration=KEYBOARD_CHAGE_DURATION) old_keyboard_instance.old_keyboard_change_animation = Animation(y=-(self.keyboard.height + BORDER_WIDTH), t='out_back', duration=KEYBOARD_CHAGE_DURATION) old_keyboard_instance.new_keyboard_change_animation.start(old_keyboard_instance.new_keyboard_instance) old_keyboard_instance.old_keyboard_change_animation.start(old_keyboard_instance) old_keyboard_instance.keyboard_is_animated = True old_keyboard_instance.new_keyboard_change_animation.bind(on_complete=self.keyboard_change_complete) def keyboard_change_complete(self, animation, widget): # first remove the old keyboard from the widget tree self.remove_widget(self.keyboard) # then make the self.keyboard reference refer to the new keyboard self.keyboard = widget self.keyboard.keyboard_is_animated = False