def add_reaction(self, reaction, index=None): """If reaction's name is not None and already exists in self._reactions, it will be replaced. Otherwise the reaction is appended to self._reactions. Remember : if you want the changes to affect the current menu, call thorpy.functions.refresh_current_menu(). """ if reaction.reac_name is None: self._reactions.append(reaction) else: index_reaction = None for (i, r) in enumerate(self._reactions): if r.reac_name == reaction.reac_name: functions.debug_msg("Reaction conflict:", r.reac_name) index_reaction = i break if index_reaction is None: self._reactions.append(reaction) else: self._reactions[index_reaction] = reaction if index: if index == -1: index = len(self._reactions) self.set_reaction_index(index, reaction)
def get_surface(self): W, H = functions.get_screen_size() surface = self.get_image() if 0 < self.alpha < 255: surface.set_alpha(self.alpha, RLEACCEL) if self.mode == "scale to screen": surface = scale(surface, (W, H)) self.size = (W, H) elif self.mode == "cut to screen": new_surface = Surface((W, H)) new_surface.blit(surface, (0, 0)) self.size = (W, H) elif self._resized: surface = scale(surface, self._resized) elif self.mode: functions.debug_msg("Unrecognized mode : ", self.mode) ## elif self._resized: ## surface = scale(surface, self._resized) if self.colorkey: surface.set_colorkey(self.colorkey, RLEACCEL) surface.set_clip(self.clip) if self.alpha < 255: return surface.convert_alpha() else: return surface.convert()
def set_size(self, size, state=None, center_title=True, adapt_text=True, cut=None, margins=None, refresh_title=False): """<margins> is used for text cutting only.""" if margins is None: margins=style.MARGINS if state is None: for state in self._states: self.set_size(size, state, center_title, adapt_text, cut, margins) else: try: if size[0] is None: sizex = self._states[state].fusionner.painter.size[0] else: sizex = size[0] if size[1] is None: sizey = self._states[state].fusionner.painter.size[1] else: sizey = size[1] size = (sizex, sizey) self._states[state].fusionner.painter.set_size(size) if adapt_text: txt_size = (size[0] - 2 * margins[0], size[1] - 2 * margins[1]) self.set_text(self._states[state].fusionner.title._text, state, center_title, txt_size, cut) refresh_title = False self.redraw(state, refresh_title=refresh_title) except AttributeError: functions.debug_msg( "Impossible to change Element's size: " + str(self) + "\n State: " + str(state)) if self._lift: self.refresh_lift()
def __init__(self, length, limvals=None, text="", elements=None, normal_params=None, initial_value=None, finish=True): if initial_value is None: initial_value = 0 if limvals[0] <= initial_value <= limvals[1]: #will be False if initial_value is None self.initial_value = initial_value else: if initial_value is not None: functions.debug_msg("Initial value for slider was not in the\ limvals range. Auto set to limvals[0].") self.initial_value = limvals[0] self._drag_element = DraggerX(self) super(SliderX, self).__init__(length, limvals, text, elements, finish=False) self._drag_element.finish() self.add_elements(list([self._drag_element])) reac_click = Reaction(pygame.MOUSEBUTTONDOWN,self._func_reac_click) self.add_reaction(reac_click) if finish: self.finish()
def _reaction_keydown(self, pygame_event): if self._activated: if pygame_event.type == KEYDOWN: if pygame_event.key == K_ESCAPE: self.exit() elif pygame_event.key == K_RETURN: # way to exit saving insertion self._value = self._inserted self.exit() functions.debug_msg("'" + self._inserted + "'", " inserted") elif pygame_event.key == K_BACKSPACE: if self._cursor_index > 0: before = self._inserted[0:self._cursor_index-1] after = self._inserted[self._cursor_index:] self._inserted = before + after self._cursor_index -= 1 self._urbu() # if this is a modifier, the next char will be handled by the # keyer... elif pygame_event.key == K_LEFT: if self._cursor_index > 1: self._cursor_index -= 1 self._urbu() elif pygame_event.key == K_RIGHT: if self._cursor_index < len(self._inserted): self._cursor_index += 1 self._urbu() elif not pygame_event.key in self._keyer.modifiers: char = self._keyer.get_char_from_key(pygame_event.key) before = self._inserted[0:self._cursor_index] after = self._inserted[self._cursor_index:] new_word = before + char + after if self._iwriter._is_small_enough(new_word): self._inserted = new_word self._cursor_index += 1 self._urbu()
def set_painter(self, painter, state=None, autopress=True): """Use before finish. If not, use set_active_painter instead.""" self.normal_params.params["painter"] = painter if self._finished: self.change_painter(painter, state, autopress) functions.debug_msg("Attention, this element is not finished : " + str(self) + ". Use set_active_painter instead")
def redraw(self, state=None, painter=None, title=None, refresh_title=False): if state is None: for state in self._states: self.redraw(state, painter, title, refresh_title) else: if painter: try: self._states[state].fusionner.painter = painter except AttributeError: functions.debug_msg( "Impossible to change Element's painter: " + str(self) + " in state: " + str(state)) if title: try: self._states[state].fusionner.title = title refresh_title = True except AttributeError: functions.debug_msg( "Impossible to change Element's title: " + str(self) + " in state: " + str(state)) self._states[state].fusionner.refresh(refresh_title=refresh_title) self._states[state].refresh_ghost_rect()
def set_size(self, size, state=None, center_title=True, adapt_text=True, cut=None, margins=style.MARGINS, refresh_title=False): """<margins> is used for text cutting only.""" if state is None: for state in self._states: self.set_size(size, state, center_title, adapt_text, cut, margins) else: try: if size[0] is None: sizex = self._states[state].fusionner.painter.size[0] else: sizex = size[0] if size[1] is None: sizey = self._states[state].fusionner.painter.size[1] else: sizey = size[1] size = (sizex, sizey) self._states[state].fusionner.painter.set_size(size) if adapt_text: txt_size = (size[0] - 2 * margins[0], size[1] - 2 * margins[1]) self.set_text(self._states[state].fusionner.title._text, state, center_title, txt_size, cut) refresh_title = False self.redraw(state, refresh_title=refresh_title) except AttributeError: functions.debug_msg( "Impossible to change Element's size: " + str(self) + "\n State: " + str(state)) if self._lift: self.refresh_lift()
def get_fusion(self, title, center_title): """Fusion the painter.img and the title.img and returns this fusion""" if title._writer.color == self.color: functions.debug_msg("Colorkey is the same as writer's color while\ generating " + title._text) if center_title is True: # center the title on the element rect title.center_on(self.size) elif center_title is not False: # center_title is the topleft argument title._pos = center_title else: title._pos = (0, 0) painter_img = self.get_surface() old_aa = title._writer.aa old_imgs = title._imgs if old_aa: title._writer.aa = False title.refresh_imgs() title.blit_on(painter_img) if old_aa: title._writer.aa = True title._imgs = old_imgs functions.debug_msg("Building illuminer of size " + str(self.size)) return illuminate_alphacolor_except(painter_img, self.color, self.color_target, self.color_bulk, self.subrect, self.factor, self.fadout, self.bulk_alpha)
def remove_from_current_menu(self): menu = functions.get_current_menu() if self.launched in menu.get_population(): menu.remove_from_population(self.launched) else: functions.debug_msg("The launched element of the launcher has been\ removed from the current menu by another element!")
def finish_population(self): """Control that all elements have been finished""" for e in self.population: if not(e._finished): functions.debug_msg(str(e) + " was not _finished !\ Automatic finish.") e.finish()
def get_value(self): try: return self._value_type(self._inserted) except ValueError: functions.debug_msg("type of self._inserted is not " + \ str(self._value_type)) return self._value_type()
def get_surface(self): W, H = functions.get_screen_size() if isinstance(self.img_path, str): # load image surface = load_image(self.img_path) else: # take image surface = self.img_path if 0 < self.alpha < 255: surface.set_alpha(self.alpha, RLEACCEL) if self.mode == "scale to screen": surface = scale(surface, (W, H)) self.size = (W, H) elif self.mode == "cut to screen": new_surface = Surface((W, H)) new_surface.blit(surface, (0, 0)) self.size = (W, H) elif self._resized: surface = scale(surface, self._resized) elif self.mode: functions.debug_msg("Unrecognized mode : ", self.mode) ## elif self._resized: ## surface = scale(surface, self._resized) if self.colorkey: surface.set_colorkey(self.colorkey, RLEACCEL) surface.set_clip(self.clip) if self.alpha < 255: return surface.convert_alpha() else: return surface.convert()
def enter(self): functions.debug_msg("Entering inserter ", self) if self.repeat_delay is not None: key_set_repeat(self.repeat_delay, self.repeat_interval) if self._hide_mouse: mouse_set_visible(False) self._activated = True self.cursor._activated = True
def insert_element(self, e): if e in self._elements: functions.debug_msg(e, " is already in ", self) raise Exception("Element already in parent.") else: self._elements.insert(0, e) self._blit_after.insert(0, e) e.father = self
def finish_population(self): """Control that all elements have been finished""" for e in self.population: if not (e._finished): functions.debug_msg( str(e) + " was not _finished !\ Automatic finish.") e.finish()
def save_screenshot(self, path=None, name=None, note=""): from thorpy.miscgui import functions if path is None: path = self.default_path if name is None: name = time.asctime().replace(" ", "_").replace(":", "-") + ".png" functions.debug_msg("Saving screenshot as " + path + note + name) pygame.image.save(functions.get_screen(), path + note + name)
def save_screenshot(self, path=None, name=None, note=""): from thorpy.miscgui import functions if path is None: path = self.default_path if name is None: name = time.asctime().replace(" ", "_").replace(":", "-") + ".png" functions.debug_msg("Saving screenshot as " + path + note + name) pygame.image.save(functions.get_screen(), path+note+name)
def append_element(self, e): if e in self._elements: functions.debug_msg(e, " is already in ", self) raise Exception("Element already in parent :", e, " is already in ", self) else: self._elements.append(e) self._blit_after.append(e) e.father = self
def enter(self): for e in self.deactivate_on_focus: e.active = False functions.debug_msg("Entering inserter ", self) if self.repeat_delay is not None: key_set_repeat(self.repeat_delay, self.repeat_interval) if self._hide_mouse: mouse_set_visible(False) self._activated = True self.cursor._activated = True
def shift(self, sign=1): sign = -sign if self.is_and_will_be_inside(sign): self.dragmove(sign) current_value = self.slider.get_value() delta = self.last_value - current_value shift_y = 1 * delta self.slider._linked.scroll_children([self.slider], (0, shift_y)) functions.debug_msg("Lift value : ", current_value) self.last_value = current_value
def _deny_child(self, child): """The difference with a normal element remove is that the child continues to see its father, though its father doesn't see it anymore. """ if child.father is not self and child.father is not None: functions.debug_msg("Attention, stealing child" + str(child) +\ " from " + str(child.father) + " to "+str(self)) child.father = self while child in self.get_elements(): self.remove_elements([child]) assert child not in self.get_elements()
def set_main_color(self, color, state=None): if state is None: for state in self._states: self.set_main_color(color, state) else: try: self._states[state].fusionner.painter.set_color(color) self.redraw(state) except AttributeError: functions.debug_msg( "Impossible to change Element's main color: ", self, "\n State: " + str(state))
def add_lift(self, axis="vertical", typ="normal"): if typ == "normal": from thorpy.elements.lift import LiftY lift_typ = LiftY elif typ == "dv": from thorpy.elements.lift import LiftDirViewerY lift_typ = LiftDirViewerY if axis == "vertical": lift = lift_typ(self) # lift is already finished self.add_elements([lift]) self._lift = lift # to access easily to the lift else: functions.debug_msg("Only vertical lift is available.")
def add_lift(self, axis="vertical", type_="normal"): if type_ == "normal": from thorpy.elements.lift import LiftY lift_typ = LiftY elif type_ == "dv": from thorpy.elements.lift import LiftDirViewerY lift_typ = LiftDirViewerY if axis == "vertical": lift = lift_typ(self) # lift is already finished lift.rank = float("inf") self.add_elements([lift]) self._lift = lift # to access easily to the lift else: functions.debug_msg("Only vertical lift is available.")
def finish(self): Clickable.finish(self) # cursor is initialized in finish because _iwriter needs self.fusionner # to initialize... self.make_small_enough(self._inserted) if not self._iwriter._is_small_enough(self._inserted): functions.debug_msg("Inserter is too small for value", self._inserted) if self.auto_resize: self.set_size(self._iwriter.get_rect().inflate((2,2)).size) self._iwriter.refresh_img() self.cursor = _Cursor(self) self.add_elements(list([self.cursor])) self._refresh_pos() self.cursor.finish() self._name_element.user_func = self.enter
def draw(self): if len(self.color) == 3 or self.color[-1] == 255: if self.size[0] < 1: debug_msg("Width < 1, automatic resize.", self) self.size = (1, self.size[1]) if self.size[1] < 1: debug_msg("Height < 1, automatic resize.", self) self.size = (self.size[0], 1) surface = Surface(self.size).convert() elif len(self.color) == 4: surface = Surface(self.size, flags=SRCALPHA).convert_alpha() else: raise Exception("Invalid color attribut") surface.fill(self.color) return surface
def _get_folders_and_files(self): try: titles = listdir(self.path) except WindowsError: functions.debug_msg("Access denied to this folder/file. Try running\ the script as administrator.") return [], [] folders = [] files = [] for title in titles: if isdir(self.path + title + "/"): folders.append(title) else: files.append(title) return folders, files
def get_fusion(self, title, center_title): """Fusion the painter.img and the title.img and returns this fusion""" if center_title is True: # center the title on the element rect title.center_on(self.size) elif center_title is not False: # center_title is the topleft argument title._pos = center_title else: title._pos = (0, 0) painter_img = self.get_surface() title.blit_on(painter_img) functions.debug_msg("Building illuminer of size " + str(self.size)) return illuminate_alphacolor_except(painter_img, self.color, self.color_target, self.color_bulk, self.subrect, self.factor, self.fadout, self.bulk_alpha)
def __init__(self, size=None, clip=None, pressed=False, hovered=False): size = style.SIZE if size is None else size w, h = size w = int(w) h = int(h) if w < 0: w = 0 debug_msg("Painter width was negative. Set to 0.") if h < 0: h = 0 debug_msg("Painter height was negative. Set to 0.") self.size = (w, h) self.clip = self.treat_clip(clip) self.original_clip = clip self.pressed = pressed self.hovered = hovered
def exit(self): key_set_repeat(parameters.KEY_DELAY, parameters.KEY_INTERVAL) if self._activated: functions.debug_msg("Leaving inserter ", self) self._inserted = self._value self._urbu() mouse_set_visible(True) self.cursor.exit() self._activated = False event_quit = event.Event(constants.THORPY_EVENT, id=constants.EVENT_INSERT, el=self, value=self._value) event.post(event_quit) if self._varlink_func: self._varlink_func(self._value)
def illuminate_alphacolor_except(surface, color_except, color_target, color_bulk=None, subrect=None, factor=1., fadout=2, bulk_alpha=255): """ mode : "except" means all the pixels that are not color_source. "exact" means all the pixels that are exacly color_source. Set fadout to 0 and bulk_alpha to 255 if you do not want alpha fade out. """ if not HAS_NUMPY: raise Exception("Could not use surfarray module from PyGame.\ NumPy is probably missing.") rect = surface.get_rect() newsurf = pygame.Surface(rect.size, SRCALPHA, depth=surface.get_bitsize()).convert_alpha() newsurf.blit(surface, (0, 0)) if subrect: rect = subrect arrayrgb = surfarray.pixels3d(newsurf) arraya = surfarray.pixels_alpha(newsurf) points = [] max_d = hypot(rect.w, rect.h) for x in range(rect.left, rect.right): for y in range(rect.top, rect.bottom): if tuple(arrayrgb[x][y]) != color_except: points.append((x, y)) if points: for x in range(rect.left, rect.right): for y in range(rect.top, rect.bottom): if not (x, y) in points: d = 1. - illuminate_dist(points, rect, x, y) / max_d d = 255 * factor * d**fadout arraya[x][y] = d arrayrgb[x][y] = color_target else: if color_bulk: arrayrgb[x][y] = color_bulk if bulk_alpha: arraya[x][y] = bulk_alpha else: functions.debug_msg("No points for illuminate alpha except") return newsurf
def blit_on(self, surface, cursor, pos=None): """Blit the files texts on self.surface, not on browser!!""" if pos: functions.debug_msg( "pos argument used for heavy dirviewer, but not handled.") i = self.get_n() y = self.get_y(i) _hovered = self.get_at_pix(cursor[0], cursor[1]) while y < self.size[1] and i < self.N: text = self.files[i] if i == _hovered: txt_img = self.writer_hover.get_img(text) else: txt_img = self.txt_imgs[i] surface.blit(txt_img, (self.x, y)) i += 1 y += self.elh + self.gap
def exit(self): key_set_repeat(parameters.KEY_DELAY, parameters.KEY_INTERVAL) if self._activated: functions.debug_msg("Leaving inserter ", self) self._inserted = self._value self._urbu() mouse_set_visible(True) self.cursor.exit() self._activated = False event_quit = event.Event(constants.THORPY_EVENT, id=constants.EVENT_INSERT, el=self, value=self._value) event.post(event_quit) if self._varlink_func: self._varlink_func(self._value) for e in self.deactivate_on_focus: e.active = True
def add_elements(self, elements, insert=False): """Use this method instead of .append, because it handles parents. If <insert>, use insert method instead of append, insert in first pos. Remember : if you want the changes to affect the current menu, call thorpy.functions.refresh_current_menu(). """ for el in elements: if not (el in self._elements): if insert: self._elements.insert(0, el) self._blit_after.insert(0, el) else: self._elements.append(el) self._blit_after.append(el) el.father = self else: functions.debug_msg(el, " is already in ", self)
def add_elements(self, elements, insert=False): """Use this method instead of .append, because it handles parents. If <insert>, use insert method instead of append. Remember : if you want the changes to affect the current menu, call thorpy.functions.refresh_current_menu(). """ for el in elements: if not(el in self._elements): if insert: self._elements.insert(0, el) self._blit_after.insert(0, el) else: self._elements.append(el) self._blit_after.append(el) el.father = self else: functions.debug_msg(el, " is already in ", self)
def __init__(self, length, limvals=None, text="", elements=None, normal_params=None, initial_value=None): if limvals[0] <= initial_value <= limvals[1]: #will be False if initial_value is None self.initial_value = initial_value else: if initial_value is not None: functions.debug_msg("Initial value for slider was not in the\ limvals range. Auto set to limvals[0].") self.initial_value = limvals[0] self._drag_element = DraggerX(self) super(SliderX, self).__init__(length, limvals, text, elements) self._drag_element.finish() self.add_elements(list([self._drag_element]))
def get_char_from_key(self, key): """<default> is returned if no character can be found from <key>""" pressed = pygame.key.get_pressed() pygame.event.pump() for (ka, kb) in self.specials: # handle combinations if pressed[ka]: if kb == key: key = self.specials[(ka, kb)] if key < 256: return chr(key) key = self._get_changed(key) if pressed[K_LSHIFT]: # handle caps if key >= 32 and key <= 126: key -= 32 debug_msg("key interpretation :", key, pygame.key.name(key)) if key < 256: return chr(key) else: return self._more_than_256(key)
def __init__(self, length, limvals=None, text="", elements=None, normal_params=None, initial_value=None): if limvals[0] <= initial_value <= limvals[ 1]: #will be False if initial_value is None self.initial_value = initial_value else: if initial_value is not None: functions.debug_msg("Initial value for slider was not in the\ limvals range. Auto set to limvals[0].") self.initial_value = limvals[0] self._drag_element = DraggerX(self) super(SliderX, self).__init__(length, limvals, text, elements) self._drag_element.finish() self.add_elements(list([self._drag_element]))
def set_blit_before(self, element): """Transfer <element> from self._elements to self._blit_before. <element> : can either be an instance of Ghost or a string. Note that this is useful when self is blitted and it must be blitted after <element>. If one blits <element> alone (i.e not by blitting self) , then <element> will of course appear as blitted after self. """ if not element in self._elements: element = self.get_elements_by_text[element] if len(element) > 0: element = element[0] if not element: raise Exception("No element found to store in blit_before.") if element in self._blit_before: functions.debug_msg(element, " was already in self._blit_before.") else: self._blit_before.append(element) self._blit_after.remove(element)
def _reaction_keydown(self, pygame_event): if self._activated: if pygame_event.type == KEYDOWN: if pygame_event.key == K_ESCAPE: self.exit() elif pygame_event.key == K_RETURN: # way to exit saving insertion self._value = self._inserted self.exit() functions.debug_msg("'" + self._inserted + "'", " inserted") elif pygame_event.key == K_BACKSPACE: if self._cursor_index > 0: before = self._inserted[0:self._cursor_index - 1] after = self._inserted[self._cursor_index:] self._inserted = before + after self._cursor_index -= 1 self._urbu() # if this is a modifier, the next char will be handled by the # keyer... elif pygame_event.key == K_LEFT: if self._cursor_index > 1: self._cursor_index -= 1 self._urbu() elif pygame_event.key == K_RIGHT: if self._cursor_index < len(self._inserted): self._cursor_index += 1 self._urbu() elif not pygame_event.key in self._keyer.modifiers: char = self._keyer.get_char_from_key(pygame_event.key) if self.numeric_only: if self.int_only and not char.isnumeric(): return elif not (char.isnumeric()) and char != ".": return before = self._inserted[0:self._cursor_index] after = self._inserted[self._cursor_index:] new_word = before + char + after if self._iwriter._is_small_enough(new_word): self._inserted = new_word self._cursor_index += 1 self._urbu()
def refresh_population(self, painting=False, placing=True, one_wheel=True): """Calls element's refresh functions. <painting> enable graphical refreshment. Caution : misc_refresh method of elements is called if placing is True. """ wheeled = None for e in self.population: if hasattr(e, "active_wheel"): if e.active_wheel: if wheeled: functions.debug_msg(str(e) + " is not the only wheel-active.") if one_wheel: e.active_wheel = False onstants.debug_msg(str(e) + " wheel was deactivated.") else: wheeled = True if painting: # used for debug e.redraw() if placing: if hasattr(e, "misc_refresh"): e.misc_refresh()
def launch_ddlf(self): self._set_branch_last() r = self.get_storer_rect() self.launched_element.set_topleft(r.bottomleft) self.add_elements([self.launched_element]) tm = TickedMenu(self.launched_element) if self.click_quit: self._quit_when_click(self.launched_element) self.launched_element._set_selecter(tm) tm.refresh() tm.play() if self.click_quit: self.launched_element.deactivate_reaction(constants.REAC_CLICKQUIT) if self.launched_element._clicked: text = normpath(self.launched_element._clicked) text = basename(text) self.selected = text functions.debug_msg(self.selected) if self.show_select: size = (self.file_width, self.get_fus_size()[1]) self.set_text(text, size=size) self._deny_child(self.launched_element) self._unlaunch()