From 7f0f5ef3c7de927fffe8389e47ddf23f7fab6a46 Mon Sep 17 00:00:00 2001 From: Conengmo <33519926+Conengmo@users.noreply.github.com> Date: Thu, 7 Dec 2023 18:52:03 +0100 Subject: [PATCH 1/6] thumbnail button wip --- battle_map_tv/gui_elements.py | 41 +++++++++++++++++++++++++++++++++++ battle_map_tv/opencv_utils.py | 28 ++++++++++++++++++++++++ battle_map_tv/window_gui.py | 41 ++++++++++++++++++++++++++++++----- 3 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 battle_map_tv/opencv_utils.py diff --git a/battle_map_tv/gui_elements.py b/battle_map_tv/gui_elements.py index 27fac83..07846b2 100644 --- a/battle_map_tv/gui_elements.py +++ b/battle_map_tv/gui_elements.py @@ -1,10 +1,17 @@ import os.path +import typing from typing import Callable, Union, Optional +import cv2 import pyglet from pyglet.graphics import Batch from pyglet.text import Label +from battle_map_tv.opencv_utils import opencv_to_pyglet_texture, change_brightness + +if typing.TYPE_CHECKING: + from battle_map_tv.window_image import ImageWindow + margin_y_label = 10 pyglet.resource.path = [os.path.join(pyglet.resource.get_script_home(), "resources")] @@ -140,6 +147,40 @@ def __init__( self.set_handler("on_release", callback) +class ThumbnailButton(CoordinatesMixin, pyglet.gui.ToggleButton): + width: int = 100 + height: int = 100 + + def __init__(self, x: int, y: int, batch: Batch, image_window: "ImageWindow"): + self.image_path: Optional[ + str + ] = "/Users/frank/Documents/battle maps/arabian city court.webp" + self.image_window = image_window + self.y_original = y + + image_cv = cv2.imread(self.image_path) + image_cv = cv2.resize(image_cv, (self.width, self.height), interpolation=cv2.INTER_AREA) + depressed = opencv_to_pyglet_texture(image_cv) + image_cv_pressed = change_brightness(image_cv, -50) + pressed = opencv_to_pyglet_texture(image_cv_pressed) + image_cv_hover = change_brightness(image_cv, 50) + hover = opencv_to_pyglet_texture(image_cv_hover) + super().__init__(x=x, y=y, pressed=pressed, depressed=depressed, hover=hover, batch=batch) + self.set_handler("on_toggle", self._custom_on_toggle) + + def hide(self): + self.y = -100 + + def show(self): + self.y = self.y_original + + def _custom_on_toggle(self, value): + if value: + self.image_window.add_image(self.image_path) + else: + self.image_window.remove_image() + + class Slider(CoordinatesMixin, pyglet.gui.Slider): base = pyglet.resource.image("slider_base.png").get_texture() knob = pyglet.resource.image("slider_knob.png").get_texture() diff --git a/battle_map_tv/opencv_utils.py b/battle_map_tv/opencv_utils.py new file mode 100644 index 0000000..88b2f12 --- /dev/null +++ b/battle_map_tv/opencv_utils.py @@ -0,0 +1,28 @@ +from io import BytesIO + +import cv2 +import pyglet + + +def change_brightness(img, value: int): + hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) + h, s, v = cv2.split(hsv) + + if value > 0: + lim = 255 - value + v[v > lim] = 255 + v[v <= lim] += value + elif value < 0: + lim = 0 - value + v[v < lim] = 0 + v[v >= lim] = v[v >= lim] + value + + final_hsv = cv2.merge((h, s, v)) + img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR) + return img + + +def opencv_to_pyglet_texture(opencv_image) -> pyglet.image.Texture: + as_bytes = cv2.imencode(".png", opencv_image)[1].tobytes() + image = pyglet.image.load(filename=".png", file=BytesIO(as_bytes)) + return image.get_texture() diff --git a/battle_map_tv/window_gui.py b/battle_map_tv/window_gui.py index 58a8ded..d75242a 100644 --- a/battle_map_tv/window_gui.py +++ b/battle_map_tv/window_gui.py @@ -15,6 +15,7 @@ PushButton, TabButton, EffectToggleButton, + ThumbnailButton, ) from battle_map_tv.scale_detection import find_image_scale from battle_map_tv.storage import get_from_storage, StorageKeys, set_in_storage @@ -195,20 +196,23 @@ def button_callback_grid(button_value: bool) -> bool: self.tab_buttons: List[TabButton] = [] + self.thumbnails: List[Thumbnail] = [] + self._add_tab_images(tab_index=0, row_y=row_y) + self.text_entry_screen_width: TextEntry self.text_entry_screen_height: TextEntry - self._add_tab_screen_size(tab_index=0, row_y=row_y) + self._add_tab_screen_size(tab_index=1, row_y=row_y) self.slider_grid_opacity: Slider - self._add_tab_grid_opacity(tab_index=1, row_y=row_y) + self._add_tab_grid_opacity(tab_index=2, row_y=row_y) self.effect_buttons: List[EffectToggleButton] = [] - self._add_tab_effects(tab_index=2, row_y=row_y) + self._add_tab_effects(tab_index=3, row_y=row_y) # Start with showing the first tab self._hide_tab_content() - self.text_entry_screen_width.show() - self.text_entry_screen_height.show() + for thumbnail in self.thumbnails: + thumbnail.show() def on_draw(self): self.clear() @@ -221,6 +225,8 @@ def on_file_drop(self, x: int, y: int, paths: List[str]): self.slider_scale.reset() def _hide_tab_content(self): + for thumbnail in self.thumbnails: + thumbnail.hide() self.text_entry_screen_width.hide() self.text_entry_screen_height.hide() self.slider_grid_opacity.hide() @@ -332,3 +338,28 @@ def callback_tab_effects(): callback=callback_tab_effects, label="Effects", ) + + def _add_tab_images(self, tab_index: int, row_y: int): + thumbnail_y = row_y + (tab_height - ThumbnailButton.height) // 2 + for i in range(1): + thumbnail_button = ThumbnailButton( + x=(2 + i) * margin_x + i * ThumbnailButton.width, + y=thumbnail_y, + batch=self.batch, + image_window=self.image_window, + ) + self.thumbnails.append(thumbnail_button) + self.frame.add_widget(thumbnail_button) + + def callback_tab_images(): + self.switch_to() + self._hide_tab_content() + for thumbnail in self.thumbnails: + thumbnail.show() + + self._create_tab_button( + tab_index=tab_index, + row_y=row_y, + callback=callback_tab_images, + label="Images", + ) From 1aa12ae75e51537fe5326754ada5e6d4ba6eb6a5 Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sat, 9 Dec 2023 12:50:16 +0100 Subject: [PATCH 2/6] mypy fixes --- battle_map_tv/gui_elements.py | 4 ++-- battle_map_tv/window_gui.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/battle_map_tv/gui_elements.py b/battle_map_tv/gui_elements.py index 07846b2..ab37c82 100644 --- a/battle_map_tv/gui_elements.py +++ b/battle_map_tv/gui_elements.py @@ -175,9 +175,9 @@ def show(self): self.y = self.y_original def _custom_on_toggle(self, value): - if value: + if value and self.image_path is not None: self.image_window.add_image(self.image_path) - else: + elif not value: self.image_window.remove_image() diff --git a/battle_map_tv/window_gui.py b/battle_map_tv/window_gui.py index a71517c..ea9c8d2 100644 --- a/battle_map_tv/window_gui.py +++ b/battle_map_tv/window_gui.py @@ -195,7 +195,7 @@ def button_callback_grid(button_value: bool) -> bool: self.tab_buttons: List[TabButton] = [] - self.thumbnails: List[Thumbnail] = [] + self.thumbnails: List[ThumbnailButton] = [] self._add_tab_images(tab_index=0, row_y=row_y) self.text_entry_screen_width: TextEntry From 47da2fc8ab8a23b1d51dac403f44494230bc2ff9 Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sat, 9 Dec 2023 13:47:40 +0100 Subject: [PATCH 3/6] properly hide gui elements --- battle_map_tv/gui_elements.py | 61 +++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/battle_map_tv/gui_elements.py b/battle_map_tv/gui_elements.py index ab37c82..5affb61 100644 --- a/battle_map_tv/gui_elements.py +++ b/battle_map_tv/gui_elements.py @@ -5,6 +5,7 @@ import cv2 import pyglet from pyglet.graphics import Batch +from pyglet.sprite import Sprite from pyglet.text import Label from battle_map_tv.opencv_utils import opencv_to_pyglet_texture, change_brightness @@ -33,6 +34,19 @@ def y2(self) -> int: return self.y + self.height +class HideButtonMixin: + enabled: bool + _sprite: Sprite + + def hide(self): + self.enabled = False + self._sprite.visible = False + + def show(self): + self._sprite.visible = True + self.enabled = True + + class TextEntry(CoordinatesMixin, pyglet.gui.TextEntry): total_height = 60 @@ -58,17 +72,17 @@ def __init__( ) self.y_original = y self.height = 30 - self.label = Label(text=label, x=self.x, batch=batch) + self.label = Label(text=label, x=self.x, y=self.y2 + margin_y_label, batch=batch) def hide(self): self.y = -100 - self.label.y = -100 + self.label.visible = False def show(self): self.y = self.y_original self._layout.x = self.x + 10 self._layout.y = self.y - 5 - self.label.y = self.y2 + margin_y_label + self.label.visible = True class PushButton(CoordinatesMixin, pyglet.gui.PushButton): @@ -102,7 +116,7 @@ def __init__(self, x: int, y: int, batch: Batch, callback: Callable, label: str, self.set_handler("on_toggle", callback) -class EffectToggleButton(pyglet.gui.ToggleButton): +class EffectToggleButton(HideButtonMixin, pyglet.gui.ToggleButton): total_height = 100 def __init__(self, x: int, y: int, batch: Batch, callback: Callable, effect: str): @@ -112,12 +126,6 @@ def __init__(self, x: int, y: int, batch: Batch, callback: Callable, effect: str super().__init__(x=x, y=y, pressed=pressed, depressed=depressed, batch=batch) self.set_handler("on_toggle", callback) - def hide(self): - self.y = -100 - - def show(self): - self.y = self.y_original - class TabButton(CoordinatesMixin, pyglet.gui.PushButton): pressed = pyglet.resource.image("tab_depressed.png").get_texture() @@ -147,17 +155,16 @@ def __init__( self.set_handler("on_release", callback) -class ThumbnailButton(CoordinatesMixin, pyglet.gui.ToggleButton): +class ThumbnailButton(CoordinatesMixin, HideButtonMixin, pyglet.gui.ToggleButton): width: int = 100 height: int = 100 def __init__(self, x: int, y: int, batch: Batch, image_window: "ImageWindow"): - self.image_path: Optional[ - str - ] = "/Users/frank/Documents/battle maps/arabian city court.webp" + self.image_path: Optional[str] = "tests/images/19d33097089ed961c4660b3a0bf671e1.png" self.image_window = image_window self.y_original = y + assert os.path.exists(self.image_path) image_cv = cv2.imread(self.image_path) image_cv = cv2.resize(image_cv, (self.width, self.height), interpolation=cv2.INTER_AREA) depressed = opencv_to_pyglet_texture(image_cv) @@ -168,12 +175,6 @@ def __init__(self, x: int, y: int, batch: Batch, image_window: "ImageWindow"): super().__init__(x=x, y=y, pressed=pressed, depressed=depressed, hover=hover, batch=batch) self.set_handler("on_toggle", self._custom_on_toggle) - def hide(self): - self.y = -100 - - def show(self): - self.y = self.y_original - def _custom_on_toggle(self, value): if value and self.image_path is not None: self.image_window.add_image(self.image_path) @@ -215,16 +216,17 @@ def __init__( self.label = Label( text=label, x=self.x, + y=self.y2 + margin_y_label, batch=batch, ) self.label_value = Label( text=label_formatter(default), x=super().x2 + 20, + y=self.y + self.height / 2, anchor_y="center", batch=batch, ) self.label_formatter = label_formatter - self.show() @property def x2(self) -> int: @@ -256,12 +258,15 @@ def reset(self): self.value = self.default def hide(self): - self.y = -100 - self.label.y = -100 - self.label_value.y = -100 + self.enabled = False + self._base_spr.visible = False + self._knob_spr.visible = False + self.label.visible = False + self.label_value.visible = False def show(self): - self.y = self.y_original - self.label.y = self.y2 + margin_y_label - self.label_value.y = self.y + self.height / 2 - self.value = self.value + self.enabled = True + self._base_spr.visible = True + self._knob_spr.visible = True + self.label.visible = True + self.label_value.visible = True From 667c0b6c97ca94c124c228bf99cf992d8f054559 Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sat, 9 Dec 2023 15:07:37 +0100 Subject: [PATCH 4/6] various tweaks to thumbnail buttons --- battle_map_tv/gui_elements.py | 77 ++++++++++++------- battle_map_tv/opencv_utils.py | 5 +- battle_map_tv/resources/button_file_drop.png | Bin 0 -> 1607 bytes battle_map_tv/window_gui.py | 18 +++-- 4 files changed, 63 insertions(+), 37 deletions(-) create mode 100644 battle_map_tv/resources/button_file_drop.png diff --git a/battle_map_tv/gui_elements.py b/battle_map_tv/gui_elements.py index 5affb61..f345678 100644 --- a/battle_map_tv/gui_elements.py +++ b/battle_map_tv/gui_elements.py @@ -5,10 +5,9 @@ import cv2 import pyglet from pyglet.graphics import Batch -from pyglet.sprite import Sprite from pyglet.text import Label -from battle_map_tv.opencv_utils import opencv_to_pyglet_texture, change_brightness +from battle_map_tv.opencv_utils import opencv_to_pyglet_image, change_brightness if typing.TYPE_CHECKING: from battle_map_tv.window_image import ImageWindow @@ -34,19 +33,6 @@ def y2(self) -> int: return self.y + self.height -class HideButtonMixin: - enabled: bool - _sprite: Sprite - - def hide(self): - self.enabled = False - self._sprite.visible = False - - def show(self): - self._sprite.visible = True - self.enabled = True - - class TextEntry(CoordinatesMixin, pyglet.gui.TextEntry): total_height = 60 @@ -116,7 +102,7 @@ def __init__(self, x: int, y: int, batch: Batch, callback: Callable, label: str, self.set_handler("on_toggle", callback) -class EffectToggleButton(HideButtonMixin, pyglet.gui.ToggleButton): +class EffectToggleButton(pyglet.gui.ToggleButton): total_height = 100 def __init__(self, x: int, y: int, batch: Batch, callback: Callable, effect: str): @@ -126,6 +112,14 @@ def __init__(self, x: int, y: int, batch: Batch, callback: Callable, effect: str super().__init__(x=x, y=y, pressed=pressed, depressed=depressed, batch=batch) self.set_handler("on_toggle", callback) + def hide(self): + self.enabled = False + self._sprite.visible = False + + def show(self): + self._sprite.visible = True + self.enabled = True + class TabButton(CoordinatesMixin, pyglet.gui.PushButton): pressed = pyglet.resource.image("tab_depressed.png").get_texture() @@ -155,31 +149,56 @@ def __init__( self.set_handler("on_release", callback) -class ThumbnailButton(CoordinatesMixin, HideButtonMixin, pyglet.gui.ToggleButton): +class ThumbnailButton(CoordinatesMixin, pyglet.gui.ToggleButton): width: int = 100 height: int = 100 def __init__(self, x: int, y: int, batch: Batch, image_window: "ImageWindow"): - self.image_path: Optional[str] = "tests/images/19d33097089ed961c4660b3a0bf671e1.png" + self.image_path: Optional[str] = None self.image_window = image_window self.y_original = y + button_img = pyglet.resource.image("button_file_drop.png") + super().__init__(x=x, y=y, pressed=button_img, depressed=button_img, batch=batch) + self.set_handler("on_toggle", self._custom_on_toggle) + def _custom_on_toggle(self, value): + if self.image_path is None: + return + if value: + self.image_window.add_image(self.image_path) + else: + self.image_window.remove_image() + + def hide(self): + self.enabled = False + self._sprite.visible = False + + def show(self): + self._sprite.visible = True + self.enabled = True + + def on_file_drop(self, x: int, y: int, image_path: str) -> bool: + if not self.enabled or not self._check_hit(x, y): + return False + self.image_path = image_path + self.add_thumbnail_image() + if self.value: + self.image_window.add_image(self.image_path) + return True + + def add_thumbnail_image(self): + assert self.image_path is not None assert os.path.exists(self.image_path) + assert self.enabled + assert self._sprite.visible image_cv = cv2.imread(self.image_path) image_cv = cv2.resize(image_cv, (self.width, self.height), interpolation=cv2.INTER_AREA) - depressed = opencv_to_pyglet_texture(image_cv) + self._depressed_img = opencv_to_pyglet_image(image_cv) image_cv_pressed = change_brightness(image_cv, -50) - pressed = opencv_to_pyglet_texture(image_cv_pressed) + self._pressed_img = opencv_to_pyglet_image(image_cv_pressed) image_cv_hover = change_brightness(image_cv, 50) - hover = opencv_to_pyglet_texture(image_cv_hover) - super().__init__(x=x, y=y, pressed=pressed, depressed=depressed, hover=hover, batch=batch) - self.set_handler("on_toggle", self._custom_on_toggle) - - def _custom_on_toggle(self, value): - if value and self.image_path is not None: - self.image_window.add_image(self.image_path) - elif not value: - self.image_window.remove_image() + self._hover_img = opencv_to_pyglet_image(image_cv_hover) + self._sprite.image = self._depressed_img class Slider(CoordinatesMixin, pyglet.gui.Slider): diff --git a/battle_map_tv/opencv_utils.py b/battle_map_tv/opencv_utils.py index 88b2f12..3eb0bc8 100644 --- a/battle_map_tv/opencv_utils.py +++ b/battle_map_tv/opencv_utils.py @@ -2,6 +2,7 @@ import cv2 import pyglet +from pyglet.image import AbstractImage def change_brightness(img, value: int): @@ -22,7 +23,7 @@ def change_brightness(img, value: int): return img -def opencv_to_pyglet_texture(opencv_image) -> pyglet.image.Texture: +def opencv_to_pyglet_image(opencv_image) -> AbstractImage: as_bytes = cv2.imencode(".png", opencv_image)[1].tobytes() image = pyglet.image.load(filename=".png", file=BytesIO(as_bytes)) - return image.get_texture() + return image diff --git a/battle_map_tv/resources/button_file_drop.png b/battle_map_tv/resources/button_file_drop.png new file mode 100644 index 0000000000000000000000000000000000000000..3981ff515953bd8e3bcf8b52d44747f9c5e64956 GIT binary patch literal 1607 zcmaJ>X;hL46eTS)3@su>B?|daX%oVwoGf?w%%DI^A`=xYDOaqqPBWDzE|Ck0TcMSF znVM^AW~r0AW*cJTm^vCd3Dp?soE)oR=vU`-=FE@x?z!*1d)|A0Zt6ao7XoeuhrwV7 zkm}CRBKK?P>uGcJE3vN@mhc%~uCS^n7^RjhJ?gU81qQ3lF!&s_Ov_h9Q(1f%%&_BY zEa{25rIjxm1>IeIuyf*f6|G1a=6U|COY{RNy!`TMfCi-$_htfVjLgS!D;3aOjPz%E{G?Md`Q z#@50E8|WDE&)HXFIo(H*ZZ8&LZqj0QP&zZSUSnE^acjbLN4p6p1?Ub0SzsQ#(xDR_ znL-|274ls}IBr(g(&DuLr>-@@!WK?1BulKcc9^##wAccww-m?(y31|>B!s_mTdk&a zlwskOLt7#OqLlY>pQQ27Kw8{l%`km2l6sC_>NsqWy;#)#|NFij;!6RJWUi{Py=Q;z zkT01lGt5(EN*b9r5IcBAtmV)f=_YAm#AKCXNQOXuRGRbh84uRnknCiiad{P0zdP$s z@smumQ;rF*33JUS=60ppWAglMW72(-3caTNWC1ddh`(9N$g(M?n8q&q;;gON3;2J2 zfR0Ny%5A6CD>H&>FAP~c1u>O)X0AAA;7tueJEjnCJO^qFFHM()_ZlIOmjyGQh>LR3 zt*0o&&88NnbnpblnLVD>8iDn@)`Z)%>9#z4!usr<;Fy=-#zU?QY^HG$(@}I`@`Qr4 zc1ymxe7;!@0KDU5p5;<><9NYTI zq&`<9y27NwO)>^8Lrb~Q9<+N86HGbnt9pSX<|`1K{8FlsqEy4xRa}ly0< z)&YA+RUuTKHx+&plNrq1UO8ejhTmIA86e;}{aP(yfLKC90ZAprs7^kduQ%%vBY9rI z6;gL!tgWn~HMK`J(9gIo2BhsEL?A99a>_34AUYA><#|?zC)H~n695v9sD9ryg`L%% zj&C>Wi+8J&2#xOuoMkZqd~cJMdm>l%oL34#0LW_gZA5#)FmK@GwrN zPhW2X@c=Q+v~GqLDr$e=%eMRL}&XhqF%^cD9pAFjYAayh;q!8c@{4Rs%FeFGJ|ysHl( zz-sfR{y$V_!e-tdF8y(czG5~5nzej7)Owm2LG5o>IFmRo_+a>6bS7oUpv?I+OJ~u`OVU~l1IwQz)qiaxh#D5qh|3EhT6ST$V@-hDj!Sf#3nYm-} zd?jCL6;7ml(0SJT2x3DV_?OsZ`Puy=BAQt@^;6q?(q#F3k=$fld~B}jv7Pn-Y~2E{ z$w)d|=+$`ra=qBzq$C9g%G+|WS*@A=2_1&~1)QKp(yvz3?5g6fun%>SEkR+5c+}h*dF0}$Oa081Y@@NcbY=Myg(#CN!*5O8P5at z>_*tr?WDK2P7Ym5!_gf6)1kgO#`o5>V7&EsR=W3NGoTcG+fR|`%;Jzw(Ir;)BUV>q zS1sLTF5F=IQBIz4XHSOZB=0JnRdX&~T$(JitE92G102P bool: self.tab_buttons: List[TabButton] = [] - self.thumbnails: List[ThumbnailButton] = [] + self.thumbnail_buttons: List[ThumbnailButton] = [] self._add_tab_images(tab_index=0, row_y=row_y) self.text_entry_screen_width: TextEntry @@ -210,7 +210,7 @@ def button_callback_grid(button_value: bool) -> bool: # Start with showing the first tab self._hide_tab_content() - for thumbnail in self.thumbnails: + for thumbnail in self.thumbnail_buttons: thumbnail.show() def on_draw(self): @@ -219,12 +219,18 @@ def on_draw(self): self.batch.draw() def on_file_drop(self, x: int, y: int, paths: List[str]): - self.image_window.add_image(image_path=paths[0]) + self.switch_to() + for thumbnail in self.thumbnail_buttons: + is_hit = thumbnail.on_file_drop(x=x, y=y, image_path=paths[0]) + if is_hit: + break + else: + self.image_window.add_image(image_path=paths[0]) self.switch_to() self.slider_scale.reset() def _hide_tab_content(self): - for thumbnail in self.thumbnails: + for thumbnail in self.thumbnail_buttons: thumbnail.hide() self.text_entry_screen_width.hide() self.text_entry_screen_height.hide() @@ -347,13 +353,13 @@ def _add_tab_images(self, tab_index: int, row_y: int): batch=self.batch, image_window=self.image_window, ) - self.thumbnails.append(thumbnail_button) + self.thumbnail_buttons.append(thumbnail_button) self.frame.add_widget(thumbnail_button) def callback_tab_images(): self.switch_to() self._hide_tab_content() - for thumbnail in self.thumbnails: + for thumbnail in self.thumbnail_buttons: thumbnail.show() self._create_tab_button( From 834117d51766c9c17e7be33586f317e2104230ea Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sat, 9 Dec 2023 15:20:34 +0100 Subject: [PATCH 5/6] deal with multiple thumbnail buttons --- battle_map_tv/gui_elements.py | 14 ++++++++++++-- battle_map_tv/window_gui.py | 14 +++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/battle_map_tv/gui_elements.py b/battle_map_tv/gui_elements.py index f345678..f09662f 100644 --- a/battle_map_tv/gui_elements.py +++ b/battle_map_tv/gui_elements.py @@ -153,10 +153,17 @@ class ThumbnailButton(CoordinatesMixin, pyglet.gui.ToggleButton): width: int = 100 height: int = 100 - def __init__(self, x: int, y: int, batch: Batch, image_window: "ImageWindow"): + def __init__( + self, + x: int, + y: int, + batch: Batch, + image_window: "ImageWindow", + all_thumbnail_buttons: list["ThumbnailButton"], + ): self.image_path: Optional[str] = None self.image_window = image_window - self.y_original = y + self.all_thumbnail_buttons = all_thumbnail_buttons button_img = pyglet.resource.image("button_file_drop.png") super().__init__(x=x, y=y, pressed=button_img, depressed=button_img, batch=batch) self.set_handler("on_toggle", self._custom_on_toggle) @@ -165,6 +172,9 @@ def _custom_on_toggle(self, value): if self.image_path is None: return if value: + for thumbnail_button in self.all_thumbnail_buttons: + if thumbnail_button is not self: + thumbnail_button.value = False self.image_window.add_image(self.image_path) else: self.image_window.remove_image() diff --git a/battle_map_tv/window_gui.py b/battle_map_tv/window_gui.py index 06394d1..489ee0e 100644 --- a/battle_map_tv/window_gui.py +++ b/battle_map_tv/window_gui.py @@ -38,6 +38,8 @@ def __init__(self, image_window: ImageWindow, *args, **kwargs): self.batch_background = Batch() self.frame = Frame(window=self) + self.thumbnail_buttons: List[ThumbnailButton] = [] + row_y = margin_y def slider_scale_callback(value: Union[float, str]): @@ -91,11 +93,17 @@ def button_callback_autoscale(button_value: bool) -> bool: row_y += 100 + def button_callback_remove(): + for thumbnail_button in self.thumbnail_buttons: + if thumbnail_button.value: + thumbnail_button.value = False + image_window.remove_image() + self.button_remove_image = PushButton( x=margin_x, y=row_y, batch=self.batch, - callback=lambda: image_window.remove_image(), + callback=button_callback_remove, label="Remove", icon="remove", ) @@ -195,7 +203,6 @@ def button_callback_grid(button_value: bool) -> bool: self.tab_buttons: List[TabButton] = [] - self.thumbnail_buttons: List[ThumbnailButton] = [] self._add_tab_images(tab_index=0, row_y=row_y) self.text_entry_screen_width: TextEntry @@ -346,12 +353,13 @@ def callback_tab_effects(): def _add_tab_images(self, tab_index: int, row_y: int): thumbnail_y = row_y + (tab_height - ThumbnailButton.height) // 2 - for i in range(1): + for i in range(4): thumbnail_button = ThumbnailButton( x=(2 + i) * margin_x + i * ThumbnailButton.width, y=thumbnail_y, batch=self.batch, image_window=self.image_window, + all_thumbnail_buttons=self.thumbnail_buttons, ) self.thumbnail_buttons.append(thumbnail_button) self.frame.add_widget(thumbnail_button) From 81cb8a23a5d88f435ea888a336095412c3c0320c Mon Sep 17 00:00:00 2001 From: Frank <33519926+Conengmo@users.noreply.github.com> Date: Sat, 9 Dec 2023 15:47:22 +0100 Subject: [PATCH 6/6] store thumbnails --- battle_map_tv/gui_elements.py | 28 ++++++++++++++++++++-------- battle_map_tv/storage.py | 4 ++++ battle_map_tv/window_gui.py | 1 + 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/battle_map_tv/gui_elements.py b/battle_map_tv/gui_elements.py index f09662f..8f70264 100644 --- a/battle_map_tv/gui_elements.py +++ b/battle_map_tv/gui_elements.py @@ -4,6 +4,7 @@ import cv2 import pyglet +from battle_map_tv.storage import set_in_storage, StorageKeys, get_from_storage, remove_from_storage from pyglet.graphics import Batch from pyglet.text import Label @@ -155,17 +156,25 @@ class ThumbnailButton(CoordinatesMixin, pyglet.gui.ToggleButton): def __init__( self, + index: int, x: int, y: int, batch: Batch, image_window: "ImageWindow", all_thumbnail_buttons: list["ThumbnailButton"], ): + self.index = index self.image_path: Optional[str] = None self.image_window = image_window self.all_thumbnail_buttons = all_thumbnail_buttons button_img = pyglet.resource.image("button_file_drop.png") super().__init__(x=x, y=y, pressed=button_img, depressed=button_img, batch=batch) + image_path = get_from_storage(self._storage_key, optional=True) + if image_path is not None: + if os.path.exists(image_path): + self.add_thumbnail_image(image_path) + else: + remove_from_storage(self._storage_key) self.set_handler("on_toggle", self._custom_on_toggle) def _custom_on_toggle(self, value): @@ -173,12 +182,16 @@ def _custom_on_toggle(self, value): return if value: for thumbnail_button in self.all_thumbnail_buttons: - if thumbnail_button is not self: + if thumbnail_button is not self and thumbnail_button.value: thumbnail_button.value = False self.image_window.add_image(self.image_path) else: self.image_window.remove_image() + @property + def _storage_key(self) -> StorageKeys: + return StorageKeys[f"thumbnail_{self.index}"] + def hide(self): self.enabled = False self._sprite.visible = False @@ -190,18 +203,17 @@ def show(self): def on_file_drop(self, x: int, y: int, image_path: str) -> bool: if not self.enabled or not self._check_hit(x, y): return False - self.image_path = image_path - self.add_thumbnail_image() + self.add_thumbnail_image(image_path) if self.value: - self.image_window.add_image(self.image_path) + self.image_window.add_image(image_path) + set_in_storage(self._storage_key, image_path) return True - def add_thumbnail_image(self): - assert self.image_path is not None - assert os.path.exists(self.image_path) + def add_thumbnail_image(self, image_path: str): + self.image_path = image_path assert self.enabled assert self._sprite.visible - image_cv = cv2.imread(self.image_path) + image_cv = cv2.imread(image_path) image_cv = cv2.resize(image_cv, (self.width, self.height), interpolation=cv2.INTER_AREA) self._depressed_img = opencv_to_pyglet_image(image_cv) image_cv_pressed = change_brightness(image_cv, -50) diff --git a/battle_map_tv/storage.py b/battle_map_tv/storage.py index 01439a8..c1df0af 100644 --- a/battle_map_tv/storage.py +++ b/battle_map_tv/storage.py @@ -31,6 +31,10 @@ class StorageKeys(Enum): width_mm = "width_mm" height_mm = "height_mm" previous_image = "previous_image" + thumbnail_0 = "thumbnail_0" + thumbnail_1 = "thumbnail_1" + thumbnail_2 = "thumbnail_2" + thumbnail_3 = "thumbnail_3" def get_from_storage(key: StorageKeys, optional: bool = False): diff --git a/battle_map_tv/window_gui.py b/battle_map_tv/window_gui.py index 489ee0e..bfc54b5 100644 --- a/battle_map_tv/window_gui.py +++ b/battle_map_tv/window_gui.py @@ -355,6 +355,7 @@ def _add_tab_images(self, tab_index: int, row_y: int): thumbnail_y = row_y + (tab_height - ThumbnailButton.height) // 2 for i in range(4): thumbnail_button = ThumbnailButton( + index=i, x=(2 + i) * margin_x + i * ThumbnailButton.width, y=thumbnail_y, batch=self.batch,