From d2c8ea91ad24cfe8b193e3239fa172a95468b82b Mon Sep 17 00:00:00 2001 From: Sander Land Date: Mon, 7 Dec 2020 22:32:57 +0100 Subject: [PATCH 1/3] shortcuts remap again --- README.md | 8 ++++---- katrain/__main__.py | 20 ++++++++++++++++---- katrain/gui/badukpan.py | 34 ++++++++++++++++++---------------- katrain/gui/kivyutils.py | 12 ++++++++++++ 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 7fa6f9a..32289e1 100644 --- a/README.md +++ b/README.md @@ -176,12 +176,12 @@ Keyboard shortcuts are shown with **[key]**. In addition to shortcuts mentioned above and those shown in the main menu: -* **[Shift]**: Open the main menu. -* **[~]** or **[ ` ]** or **[f12]**: Cycles through more minimalistic UI modes. +* **[Alt]**: Open the main menu. +* **[~]** or **[ ` ]** or **[F12]**: Cycles through more minimalistic UI modes. * **[p]**: Pass * **[pause]**: Pause/Resume timer -* **[arrow left]** or **[z]**: Undo move. Hold alt for 10 moves at a time, or ctrl to skip to the start. -* **[arrow right]** or **[x]**: Redo move. Hold alt for 10 moves at a time, or ctrl to skip to the end. +* **[arrow left]** or **[z]**: Undo move. Hold shift for 10 moves at a time, or ctrl to skip to the start. +* **[arrow right]** or **[x]**: Redo move. Hold shift for 10 moves at a time, or ctrl to skip to the end. * **[arrow up/down]** Switch branch, as would be expected from the move tree. * **[home/end]** Go to the beginning/end of the game. * **[pageup]** Make the currently selected node the main branch diff --git a/katrain/__main__.py b/katrain/__main__.py index 6989370..adda0dd 100644 --- a/katrain/__main__.py +++ b/katrain/__main__.py @@ -537,12 +537,11 @@ class KaTrainGui(Screen, KaTrainBase): else: return ctrl_pressed = "ctrl" in modifiers - alt_pressed = "alt" in modifiers shift_pressed = "shift" in modifiers shortcuts = self.shortcuts if keycode[1] == "tab": self.play_mode.switch_ui_mode() - elif keycode[1] == "shift": + elif keycode[1] == "alt": self.nav_drawer.set_state("toggle") elif keycode[1] == "spacebar": self.toggle_continuous_analysis() @@ -551,9 +550,9 @@ class KaTrainGui(Screen, KaTrainBase): elif keycode[1] in ["`", "~", "f12"]: self.zen = (self.zen + 1) % 3 elif keycode[1] in ["left", "z"]: - self("undo", 1 + (alt_pressed or shift_pressed) * 9 + (ctrl_pressed and not alt_pressed) * 999) + self("undo", 1 + shift_pressed * 9 + ctrl_pressed * 999) elif keycode[1] in ["right", "x"]: - self("redo", 1 + (alt_pressed or shift_pressed) * 9 + (ctrl_pressed and not alt_pressed) * 999) + self("redo", 1 + shift_pressed * 9 + ctrl_pressed * 999) elif keycode[1] == "home": self("undo", 999) elif keycode[1] == "end": @@ -583,6 +582,17 @@ class KaTrainGui(Screen, KaTrainBase): shortcut.trigger_action(duration=0) else: self(*shortcut) + elif keycode[1] == "f9" and self.debug_level >= OUTPUT_EXTRA_DEBUG: + import yappi + yappi.set_clock_type("cpu") + yappi.start() + self.log("starting profiler",OUTPUT_ERROR) + elif keycode[1] == "f10" and self.debug_level >= OUTPUT_EXTRA_DEBUG: + import yappi, time + stats = yappi.get_func_stats() + filename =f"callgrind.{int(time.time())}.prof" + stats.save(filename, type='callgrind') + self.log(f"wrote profiling results to {filename}", OUTPUT_ERROR) return True @@ -594,6 +604,7 @@ class KaTrainApp(MDApp): super().__init__() def build(self): + global DEFAULT_FONT self.icon = ICON # how you're supposed to set an icon self.title = f"KaTrain v{VERSION}" @@ -604,6 +615,7 @@ class KaTrainApp(MDApp): kv_file = find_package_resource("katrain/gui.kv") popup_kv_file = find_package_resource("katrain/popups.kv") resource_add_path(PATHS["PACKAGE"]) + DEFAULT_FONT = cached_resource_find(DEFAULT_FONT) Builder.load_file(kv_file) Window.bind(on_request_close=self.on_request_close) diff --git a/katrain/gui/badukpan.py b/katrain/gui/badukpan.py index 4a610d0..32cf86c 100644 --- a/katrain/gui/badukpan.py +++ b/katrain/gui/badukpan.py @@ -33,11 +33,12 @@ from katrain.core.constants import ( from katrain.core.game import Move from katrain.core.lang import i18n from katrain.core.utils import evaluation_class, format_visits, var_to_grid -from katrain.gui.kivyutils import BackgroundMixin, draw_circle, draw_text +from katrain.gui.kivyutils import BackgroundMixin, draw_circle, draw_text, cached_resource_find from katrain.gui.popups import I18NPopup, ReAnalyzeGamePopup from katrain.gui.style import * + class BadukPanWidget(Widget): def __init__(self, **kwargs): super(BadukPanWidget, self).__init__(**kwargs) @@ -55,8 +56,9 @@ class BadukPanWidget(Widget): self.animating_pv = None self.last_mouse_pos = (0, 0) Window.bind(mouse_pos=self.on_mouse_pos) - self.redraw_board_contents_trigger = Clock.create_trigger(self.draw_board_contents) - self.redraw_trigger = Clock.create_trigger(self.redraw) + self.redraw_board_contents_trigger = Clock.create_trigger(self.draw_board_contents,0.05) + self.redraw_trigger = Clock.create_trigger(self.redraw,0.05) + self.redraw_hover_contents_trigger = Clock.create_trigger(self.draw_hover_contents,0.01) self.bind(size=self.redraw_trigger, pos=self.redraw_trigger) Clock.schedule_interval(self.animate_pv, 0.1) @@ -81,7 +83,7 @@ class BadukPanWidget(Widget): else: self.ghost_stone = None if prev_ghost != self.ghost_stone: - self.draw_hover_contents() + self.redraw_hover_contents_trigger() def update_box_selection(self, touch, second_point=True): if not self.gridpos_x: @@ -93,7 +95,7 @@ class BadukPanWidget(Widget): self.region_of_interest[3] = yp else: self.region_of_interest = [xp, xp, yp, yp] - self.draw_hover_contents() + self.redraw_hover_contents_trigger() def on_touch_down(self, touch): self.set_animating_pv(None, None) # any click kills PV from label/move @@ -186,7 +188,7 @@ class BadukPanWidget(Widget): self.set_animating_pv(nodes_here[-1].parent.candidate_moves[0]["pv"], nodes_here[-1].parent) self.ghost_stone = None - self.draw_hover_contents() # remove ghost + self.redraw_hover_contents_trigger() # remove ghost # drawing functions def redraw(self, *_args): @@ -199,7 +201,7 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[x] - stone_size, self.gridpos_y[y] - stone_size), size=(2 * stone_size, 2 * stone_size), - source=f"img/{player}_stone.png", + source=cached_resource_find(f"img/{player}_stone.png"), ) if evalcol: eval_radius = math.sqrt(evalscale) # scale area by evalscale @@ -208,7 +210,7 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[x] - evalsize, self.gridpos_y[y] - evalsize), size=(2 * evalsize, 2 * evalsize), - source=f"img/dot.png", + source=cached_resource_find(f"img/dot.png"), ) if innercol: Color(*innercol) @@ -216,7 +218,7 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[x] - inner_size, self.gridpos_y[y] - inner_size), size=(2 * inner_size, 2 * inner_size), - source=f"img/inner.png", + source=cached_resource_find(f"img/inner.png"), ) def eval_color(self, points_lost, show_dots_for_class: List[bool] = None) -> Optional[List[float]]: @@ -261,7 +263,7 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[0] - self.grid_size * 1.5, self.gridpos_y[0] - self.grid_size * 1.5), size=(self.grid_size * x_grid_spaces, self.grid_size * y_grid_spaces), - source="img/board.png", + source=cached_resource_find("img/board.png"), ) Color(*LINE_COLOR) @@ -455,7 +457,7 @@ class BadukPanWidget(Widget): pos=center, text=text, font_size=size * 0.25, halign="center", outline_color=[0.95, 0.95, 0.95] ) - self.draw_hover_contents() + self.redraw_hover_contents_trigger() def draw_roi_box(self, region_of_interest, width=2): xmin, xmax, ymin, ymax = region_of_interest @@ -547,9 +549,9 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[move.coords[0]] - evalsize, self.gridpos_y[move.coords[1]] - evalsize), size=(2 * evalsize, 2 * evalsize), - source="img/topmove.png", + source=cached_resource_find("img/topmove.png"), ) - if text_on and top_moves_show: + if text_on and top_moves_show: # TODO: faster if not sized? keys = {"size": self.grid_size / 3, "smallsize": self.grid_size / 3.33} player_sign = current_node.player_sign(current_node.next_player) if len(top_moves_show) == 1: @@ -649,7 +651,7 @@ class BadukPanWidget(Widget): def animate_pv(self, _dt): if self.animating_pv: - self.draw_hover_contents() + self.redraw_hover_contents_trigger() def draw_pv(self, pv, node, up_to_move): katrain = self.katrain @@ -684,7 +686,7 @@ class BadukPanWidget(Widget): Rectangle( # not sure why the -1 here, but seems to center better pos=(board_coords[0] - stone_size - 1, board_coords[1] - stone_size), size=(2 * stone_size + 1, 2 * stone_size + 1), - source=f"img/{move_player}_stone.png", + source=cached_resource_find(f"img/{move_player}_stone.png"), ) Color(*STONE_TEXT_COLORS[move_player]) draw_text(pos=board_coords, text=str(i + 1), font_size=self.grid_size * sizefac / 1.45, font_name="Roboto") @@ -696,7 +698,7 @@ class BadukPanWidget(Widget): not self.animating_pv or not (self.animating_pv[0] == pv and self.animating_pv[1] == node) ): self.animating_pv = (pv, node, time.time(), self.last_mouse_pos) - self.draw_hover_contents() + self.redraw_hover_contents_trigger() def show_pv_from_comments(self, pv_str): self.set_animating_pv(pv_str[1:].split(" "), self.katrain.controls.active_comment_node.parent) diff --git a/katrain/gui/kivyutils.py b/katrain/gui/kivyutils.py index 7a31005..ad2cda4 100644 --- a/katrain/gui/kivyutils.py +++ b/katrain/gui/kivyutils.py @@ -1,3 +1,5 @@ +import functools + from kivy.clock import Clock from kivy.core.text import Label as CoreLabel from kivy.core.text.markup import MarkupLabel as CoreMarkupLabel @@ -11,6 +13,7 @@ from kivy.properties import ( OptionProperty, StringProperty, ) +from kivy.resources import resource_find from kivy.uix.behaviors import ButtonBehavior, FocusBehavior, ToggleButtonBehavior from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button @@ -623,3 +626,12 @@ def draw_text(pos, text, font_name=None, markup=False, **kw): def draw_circle(pos, r, col): Color(*col) Ellipse(pos=(pos[0] - r, pos[1] - r), size=(2 * r, 2 * r)) + + +def cached_resource_find(path,force_reload=False,_cache={}): + return path + result = _cache.get(path) + if force_reload or not result: + result = _cache[path] = resource_find(path) + return result + From a51e9c3accd304ce8667601df0cc0a8caad73236 Mon Sep 17 00:00:00 2001 From: Sander Land Date: Mon, 7 Dec 2020 22:51:57 +0100 Subject: [PATCH 2/3] black/cache --- katrain/__main__.py | 8 +++++--- katrain/gui/badukpan.py | 9 ++++----- katrain/gui/kivyutils.py | 4 +--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/katrain/__main__.py b/katrain/__main__.py index adda0dd..3735a88 100644 --- a/katrain/__main__.py +++ b/katrain/__main__.py @@ -584,14 +584,16 @@ class KaTrainGui(Screen, KaTrainBase): self(*shortcut) elif keycode[1] == "f9" and self.debug_level >= OUTPUT_EXTRA_DEBUG: import yappi + yappi.set_clock_type("cpu") yappi.start() - self.log("starting profiler",OUTPUT_ERROR) + self.log("starting profiler", OUTPUT_ERROR) elif keycode[1] == "f10" and self.debug_level >= OUTPUT_EXTRA_DEBUG: import yappi, time + stats = yappi.get_func_stats() - filename =f"callgrind.{int(time.time())}.prof" - stats.save(filename, type='callgrind') + filename = f"callgrind.{int(time.time())}.prof" + stats.save(filename, type="callgrind") self.log(f"wrote profiling results to {filename}", OUTPUT_ERROR) return True diff --git a/katrain/gui/badukpan.py b/katrain/gui/badukpan.py index 32cf86c..85bd932 100644 --- a/katrain/gui/badukpan.py +++ b/katrain/gui/badukpan.py @@ -38,7 +38,6 @@ from katrain.gui.popups import I18NPopup, ReAnalyzeGamePopup from katrain.gui.style import * - class BadukPanWidget(Widget): def __init__(self, **kwargs): super(BadukPanWidget, self).__init__(**kwargs) @@ -56,9 +55,9 @@ class BadukPanWidget(Widget): self.animating_pv = None self.last_mouse_pos = (0, 0) Window.bind(mouse_pos=self.on_mouse_pos) - self.redraw_board_contents_trigger = Clock.create_trigger(self.draw_board_contents,0.05) - self.redraw_trigger = Clock.create_trigger(self.redraw,0.05) - self.redraw_hover_contents_trigger = Clock.create_trigger(self.draw_hover_contents,0.01) + self.redraw_board_contents_trigger = Clock.create_trigger(self.draw_board_contents, 0.05) + self.redraw_trigger = Clock.create_trigger(self.redraw, 0.05) + self.redraw_hover_contents_trigger = Clock.create_trigger(self.draw_hover_contents, 0.01) self.bind(size=self.redraw_trigger, pos=self.redraw_trigger) Clock.schedule_interval(self.animate_pv, 0.1) @@ -551,7 +550,7 @@ class BadukPanWidget(Widget): size=(2 * evalsize, 2 * evalsize), source=cached_resource_find("img/topmove.png"), ) - if text_on and top_moves_show: # TODO: faster if not sized? + if text_on and top_moves_show: # TODO: faster if not sized? keys = {"size": self.grid_size / 3, "smallsize": self.grid_size / 3.33} player_sign = current_node.player_sign(current_node.next_player) if len(top_moves_show) == 1: diff --git a/katrain/gui/kivyutils.py b/katrain/gui/kivyutils.py index ad2cda4..37bb0a8 100644 --- a/katrain/gui/kivyutils.py +++ b/katrain/gui/kivyutils.py @@ -628,10 +628,8 @@ def draw_circle(pos, r, col): Ellipse(pos=(pos[0] - r, pos[1] - r), size=(2 * r, 2 * r)) -def cached_resource_find(path,force_reload=False,_cache={}): - return path +def cached_resource_find(path, force_reload=False, _cache={}): result = _cache.get(path) if force_reload or not result: result = _cache[path] = resource_find(path) return result - From feee858967978b1acad886ed907479e1e2e79535 Mon Sep 17 00:00:00 2001 From: Sander Land Date: Mon, 7 Dec 2020 23:24:57 +0100 Subject: [PATCH 3/3] better cache --- katrain/__main__.py | 2 +- katrain/gui/badukpan.py | 14 +++++++------- katrain/gui/kivyutils.py | 13 ++++++++----- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/katrain/__main__.py b/katrain/__main__.py index 3735a88..71d6783 100644 --- a/katrain/__main__.py +++ b/katrain/__main__.py @@ -617,7 +617,7 @@ class KaTrainApp(MDApp): kv_file = find_package_resource("katrain/gui.kv") popup_kv_file = find_package_resource("katrain/popups.kv") resource_add_path(PATHS["PACKAGE"]) - DEFAULT_FONT = cached_resource_find(DEFAULT_FONT) + DEFAULT_FONT = resource_find(DEFAULT_FONT) Builder.load_file(kv_file) Window.bind(on_request_close=self.on_request_close) diff --git a/katrain/gui/badukpan.py b/katrain/gui/badukpan.py index 85bd932..7c404c5 100644 --- a/katrain/gui/badukpan.py +++ b/katrain/gui/badukpan.py @@ -33,7 +33,7 @@ from katrain.core.constants import ( from katrain.core.game import Move from katrain.core.lang import i18n from katrain.core.utils import evaluation_class, format_visits, var_to_grid -from katrain.gui.kivyutils import BackgroundMixin, draw_circle, draw_text, cached_resource_find +from katrain.gui.kivyutils import BackgroundMixin, draw_circle, draw_text, cached_texture from katrain.gui.popups import I18NPopup, ReAnalyzeGamePopup from katrain.gui.style import * @@ -200,7 +200,7 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[x] - stone_size, self.gridpos_y[y] - stone_size), size=(2 * stone_size, 2 * stone_size), - source=cached_resource_find(f"img/{player}_stone.png"), + texture=cached_texture(f"img/{player}_stone.png"), ) if evalcol: eval_radius = math.sqrt(evalscale) # scale area by evalscale @@ -209,7 +209,7 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[x] - evalsize, self.gridpos_y[y] - evalsize), size=(2 * evalsize, 2 * evalsize), - source=cached_resource_find(f"img/dot.png"), + texture=cached_texture(f"img/dot.png"), ) if innercol: Color(*innercol) @@ -217,7 +217,7 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[x] - inner_size, self.gridpos_y[y] - inner_size), size=(2 * inner_size, 2 * inner_size), - source=cached_resource_find(f"img/inner.png"), + texture=cached_texture(f"img/inner.png"), ) def eval_color(self, points_lost, show_dots_for_class: List[bool] = None) -> Optional[List[float]]: @@ -262,7 +262,7 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[0] - self.grid_size * 1.5, self.gridpos_y[0] - self.grid_size * 1.5), size=(self.grid_size * x_grid_spaces, self.grid_size * y_grid_spaces), - source=cached_resource_find("img/board.png"), + texture=cached_texture("img/board.png"), ) Color(*LINE_COLOR) @@ -548,7 +548,7 @@ class BadukPanWidget(Widget): Rectangle( pos=(self.gridpos_x[move.coords[0]] - evalsize, self.gridpos_y[move.coords[1]] - evalsize), size=(2 * evalsize, 2 * evalsize), - source=cached_resource_find("img/topmove.png"), + texture=cached_texture("img/topmove.png"), ) if text_on and top_moves_show: # TODO: faster if not sized? keys = {"size": self.grid_size / 3, "smallsize": self.grid_size / 3.33} @@ -685,7 +685,7 @@ class BadukPanWidget(Widget): Rectangle( # not sure why the -1 here, but seems to center better pos=(board_coords[0] - stone_size - 1, board_coords[1] - stone_size), size=(2 * stone_size + 1, 2 * stone_size + 1), - source=cached_resource_find(f"img/{move_player}_stone.png"), + texture=cached_texture(f"img/{move_player}_stone.png"), ) Color(*STONE_TEXT_COLORS[move_player]) draw_text(pos=board_coords, text=str(i + 1), font_size=self.grid_size * sizefac / 1.45, font_name="Roboto") diff --git a/katrain/gui/kivyutils.py b/katrain/gui/kivyutils.py index 37bb0a8..eb621ba 100644 --- a/katrain/gui/kivyutils.py +++ b/katrain/gui/kivyutils.py @@ -1,6 +1,8 @@ import functools +from kivy.cache import Cache from kivy.clock import Clock +from kivy.core.image import Image from kivy.core.text import Label as CoreLabel from kivy.core.text.markup import MarkupLabel as CoreMarkupLabel from kivy.core.window import Window @@ -628,8 +630,9 @@ def draw_circle(pos, r, col): Ellipse(pos=(pos[0] - r, pos[1] - r), size=(2 * r, 2 * r)) -def cached_resource_find(path, force_reload=False, _cache={}): - result = _cache.get(path) - if force_reload or not result: - result = _cache[path] = resource_find(path) - return result +# direct cache to texture, bypassing resource_find +def cached_texture(path,_cache={}): + tex = _cache.get(path) + if not tex: + tex = _cache[path] = Image(resource_find(path)).texture + return tex