diff --git a/webui/flet/scripts/flet_asset_manager.py b/webui/flet/scripts/flet_asset_manager.py index 7f11881..cd06679 100644 --- a/webui/flet/scripts/flet_asset_manager.py +++ b/webui/flet/scripts/flet_asset_manager.py @@ -171,28 +171,28 @@ asset_manager = AssetManager( content = ft.Row( controls = [ ft.Column( - controls = [ - ft.Tabs( - selected_index = 0, - animation_duration = 300, - tabs = [ - ft.Tab( - content = layer_panel, - tab_content = ft.Text( - value = "Layers", - ), - ), - ft.Tab( - content = asset_panel, - tab_content = ft.Text( - value = "Assets", - ), - ), - ], - ), - ], - alignment = 'start', - expand = True + controls = [ + ft.Tabs( + selected_index = 0, + animation_duration = 300, + tabs = [ + ft.Tab( + content = layer_panel, + tab_content = ft.Text( + value = "Layers", + ), + ), + ft.Tab( + content = asset_panel, + tab_content = ft.Text( + value = "Assets", + ), + ), + ], + ), + ], + alignment = 'start', + expand = True ), asset_manager_dragbar, ], diff --git a/webui/flet/scripts/flet_canvas.py b/webui/flet/scripts/flet_canvas.py index d295980..643f40b 100644 --- a/webui/flet/scripts/flet_canvas.py +++ b/webui/flet/scripts/flet_canvas.py @@ -17,17 +17,18 @@ class Canvas(ft.Container): self.overlay.tools.zoom_in = self.page.icon_size self.overlay.tools.zoom_out = self.page.icon_size - self.overlay.canvas_size.content.color = self.page.text_color - self.overlay.canvas_size.content.size = self.page.text_size + self.overlay.size_display.content.color = self.page.text_color + self.overlay.size_display.content.size = self.page.text_size self.add_canvas_background() self.center_canvas(self) self.refresh_canvas() + self.update() def lock_canvas(self): - self.overlay.canvas_cover.lock_canvas() + self.overlay.cover.lock_canvas() def unlock_canvas(self): - self.overlay.canvas_cover.unlock_canvas() + self.overlay.cover.unlock_canvas() def refresh_canvas(self): self.overlay.refresh_canvas_overlay() @@ -42,18 +43,25 @@ class Canvas(ft.Container): self.image_stack.add_layer_image(image) self.update() + def get_image_stack_preview(self): + return self.image_stack.get_preview() + def center_canvas(self, e): width, height = self.page.get_viewport_size() self.image_stack.offset_x = 0 self.image_stack.offset_y = 0 self.image_stack.left = (width * 0.5) - (self.image_stack.width * 0.5) self.image_stack.top = (height * 0.5) - (self.image_stack.height * 0.5) + self.overlay.preview.left = self.image_stack.left + self.overlay.preview.top = self.image_stack.top self.update() def align_canvas(self, e): width, height = self.page.get_viewport_size() self.image_stack.left = (width * 0.5) - (self.image_stack.width * 0.5) + self.image_stack.offset_x self.image_stack.top = (height * 0.5) - (self.image_stack.height * 0.5) + self.image_stack.offset_y + self.overlay.preview.left = self.image_stack.left + self.overlay.preview.top = self.image_stack.top self.update() def pan_canvas(self, e: ft.DragUpdateEvent): @@ -72,6 +80,7 @@ class Canvas(ft.Container): else: self.image_stack.scale += 0.05 self.image_stack.get_scaled_size() + self.overlay.preview.scale = self.image_stack.scale self.align_canvas(e) def zoom_out(self, e): @@ -79,6 +88,7 @@ class Canvas(ft.Container): self.image_stack.scale = 0.1 else: self.image_stack.scale -= 0.05 + self.overlay.preview.scale = self.image_stack.scale self.image_stack.get_scaled_size() self.align_canvas(e) @@ -101,6 +111,7 @@ class ImageStack(ft.Container): gapless_playback = True, ), ) + canvas_bg.image = image self.canvas_bg = canvas_bg self.content.controls.append(canvas_bg) @@ -111,15 +122,22 @@ class ImageStack(ft.Container): width = image.width, height = image.height, content = ft.Image( - src = f'assets/uploads/{image.filename}', + src = f'{image.path}', width = image.width, height = image.height, gapless_playback = True, ), ) + layer_image.image = image self.center_layer(layer_image) self.content.controls.append(layer_image) - canvas.layers.append(layer_image) + canvas.refresh_canvas() + + def get_preview(self): + stack = [] + for layer in self.content.controls: + stack.append(layer.image) + return flet_utils.get_preview_from_stack(self.page.canvas_size, stack) def get_scaled_size(self): self.scaled_width = self.width * self.scale @@ -151,11 +169,20 @@ class LayerImage(ft.Container): class CanvasOverlay(ft.Stack): def refresh_canvas_overlay(self): self.refresh_canvas_size_display() + self.refresh_canvas_preview() def refresh_canvas_size_display(self): - self.canvas_size.content.value = str(self.page.canvas_size) + self.size_display.content.value = str(self.page.canvas_size) self.update() + def refresh_canvas_preview(self): + preview = canvas.get_image_stack_preview() + self.preview.content.src_base64 = flet_utils.convert_image_to_base64(preview) + self.preview.content.width = preview.width + self.preview.content.height = preview.height + self.preview.image = preview + self.page.property_manager.set_preview_image(preview) + def pan_canvas(e): canvas.pan_canvas(e) @@ -175,40 +202,33 @@ image_stack.scaled_width = image_stack.width image_stack.scaled_height = image_stack.height -class CanvasCover(ft.Container): - def lock_canvas(self): - self.bgcolor = 'black' - self.opacity = 0.5, - self.content = self.loading +canvas_cover = ft.Container( + content = None, + expand = True, + bgcolor = 'black', + opacity = 0.5, +) - def unlock_canvas(self): - self.bgcolor = None - self.opacity = 1.0, - self.content = self.detector +canvas_preview = LayerImage( + width = 4096, + height = 4096, + padding = 0, + margin = 0, + image_fit = ft.ImageFit.CONTAIN, + alignment = ft.alignment.center, + content = ft.Image( + src_base64 = None, + gapless_playback = True, + ), +) -gesture_detector = ft.GestureDetector( + +canvas_gestures = ft.GestureDetector( mouse_cursor = ft.MouseCursor.MOVE, drag_interval = 10, on_pan_update = pan_canvas, ) -canvas_loading = ft.ProgressRing( - width = 50, - height = 50, - stroke_width = 4, - value = None, -) - -canvas_cover = CanvasCover( - content = gesture_detector, - expand = True, - bgcolor = None, - opacity = 1.0, -) - -canvas_cover.detector = gesture_detector -canvas_cover.loading = canvas_loading - canvas_size_display = ft.Container( content = ft.Text( value = "test", @@ -273,13 +293,16 @@ canvas_tools.zoom_out = zoom_out_button canvas_overlay = CanvasOverlay( [ canvas_cover, + canvas_preview, + canvas_gestures, canvas_size_display, canvas_tools, ], ) -canvas_overlay.canvas_cover = canvas_cover -canvas_overlay.canvas_size = canvas_size_display +canvas_overlay.cover = canvas_cover +canvas_overlay.preview = canvas_preview +canvas_overlay.size_display = canvas_size_display canvas_overlay.tools = canvas_tools @@ -298,4 +321,4 @@ canvas = Canvas( canvas.image_stack = image_stack canvas.overlay = canvas_overlay -canvas.layers = [] + diff --git a/webui/flet/scripts/flet_gallery_window.py b/webui/flet/scripts/flet_gallery_window.py index f4738d7..cbe31a9 100644 --- a/webui/flet/scripts/flet_gallery_window.py +++ b/webui/flet/scripts/flet_gallery_window.py @@ -85,16 +85,22 @@ class GalleryDisplay(ft.Container): if 'info_path' in image[image_name]: image_data = image[image_name]['info_path'] self.content.controls[0].controls.append( - ft.Image( - src = image_path, - tooltip = image_name, - gapless_playback = True, + ft.Container( + content = ft.Image( + src = image_path, + tooltip = image_name, + gapless_playback = True, + ), + image_fit = ft.ImageFit.CONTAIN, + padding = 0, + margin = 0, + on_click = ) ) def add_as_new_layer(e): - pass + e.page.asset_manager.add_image_as_layer(gallery_window.selected_image) def save_to_disk(e): pass @@ -153,4 +159,4 @@ gallery_window = GalleryWindow( gallery_window.uploads_gallery = uploads_gallery gallery_window.outputs_gallery = outputs_gallery - +gallery_window.selected_image = None diff --git a/webui/flet/scripts/flet_property_manager.py b/webui/flet/scripts/flet_property_manager.py index 9794acf..f1f21ac 100644 --- a/webui/flet/scripts/flet_property_manager.py +++ b/webui/flet/scripts/flet_property_manager.py @@ -19,6 +19,9 @@ class PropertyManager(ft.Container): self.set_tab_margin(self.page.container_margin) self.dragbar.content.width = self.page.vertical_divider_width self.dragbar.content.color = self.page.tertiary_color + self.property_panel.preview.width = self.page.right_panel_width + self.property_panel.preview_dragbar.content.content.height = self.page.divider_height + self.property_panel.preview_dragbar.content.content.color = self.page.tertiary_color def set_tab_text_size(self, size): for tab in self.tabs: @@ -36,33 +39,69 @@ class PropertyManager(ft.Container): for tab in self.tabs: tab.content.margin = margin + def set_preview_size(self, width): + self.property_panel.preview.width = width + + def set_preview_image(self, image): + self.property_panel.preview.content.src_base64 = flet_utils.convert_image_to_base64(image) + self.property_panel.update() class PropertyPanel(ft.Container): - pass + def resize_preview(self, e): + self.page.preview_height = max(200, self.page.preview_height + e.delta_y) + self.preview.height = self.page.preview_height + self.update() + +preview_pane = ft.Container( + content = ft.Image( + src_base64 = None, + gapless_playback = True, + ), + image_fit = ft.ImageFit.CONTAIN, + bgcolor = 'black', + height = 200, + padding = 0, + margin = 0, +) + +def resize_preview(e): + property_panel.resize_preview(e) + +preview_dragbar = ft.GestureDetector( + mouse_cursor = ft.MouseCursor.RESIZE_ROW, + drag_interval = 50, + on_pan_update = resize_preview, + content = ft.Container( + content = ft.Divider(), + margin = 0, + padding = 0, + ), +) property_panel = PropertyPanel( content = ft.Column( - spacing = 0, controls = [ - ft.Text("Under Construction"), + preview_pane, + preview_dragbar, ], ), - clip_behavior = 'antiAlias', ) +property_panel.preview = preview_pane +property_panel.preview_dragbar = preview_dragbar + output_panel = PropertyPanel( content = ft.Column( - spacing = 0, controls = [ - ft.Text("Under Construction."), + ft.Text("Under Construction."), ], ), - clip_behavior = 'antiAlias', ) def resize_property_manager(e: ft.DragUpdateEvent): e.page.right_panel_width = max(250, e.page.right_panel_width - e.delta_x) property_manager.width = e.page.right_panel_width + property_panel.preview.width = e.page.right_panel_width e.page.update() property_manager_dragbar = ft.GestureDetector( @@ -82,24 +121,28 @@ property_manager = PropertyManager( selected_index = 0, animation_duration = 300, tabs = [ - ft.Tab( - content = property_panel, - tab_content = ft.Text( - value = "Properties", - ), - ), - ft.Tab( - content = output_panel, - tab_content = ft.Text( - value = "Output", - ), - ), + ft.Tab( + content = property_panel, + tab_content = ft.Text( + value = "Properties", + ), + ), + ft.Tab( + content = output_panel, + tab_content = ft.Text( + value = "Output", + ), + ), ], ), ], alignment = 'start', expand = True ), + ft.VerticalDivider( + width = 4, + opacity = 0, + ), ], expand = True, ), diff --git a/webui/flet/scripts/flet_utils.py b/webui/flet/scripts/flet_utils.py index 8787ea6..e5082f8 100644 --- a/webui/flet/scripts/flet_utils.py +++ b/webui/flet/scripts/flet_utils.py @@ -85,6 +85,7 @@ def get_image_from_uploads(name): image = Image.open(path_to_image) image = image.convert("RGBA") image.filename = name + image.path = path_to_image return image else: log_message(f'image not found: "{name}"') @@ -97,16 +98,18 @@ def get_canvas_background(path): # takes list of Image(s) as arg # returns single composite of all images -def get_visible_from_image_stack(image_list): - visible_image = create_blank_image() - for image in image_list: +def get_preview_from_stack(size, images): + preview = create_blank_image(size) + canvas_width = size[0] + canvas_height = size[1] + for image in images: # need to crop images for composite - x0, y0 = (image.width * 0.5) - 256, (image.height * 0.5) - 256 - x1, y1 = x0 + 512, y0 + 512 + x0, y0 = (image.width - canvas_width) * 0.5, (image.height - canvas_height) * 0.5 + x1, y1 = x0 + canvas_width, y0 + canvas_height box = (x0, y0, x1, y1) cropped_image = image.crop(box) - visible_image = Image.alpha_composite(visible_image,cropped_image) - return visible_image + preview = Image.alpha_composite(preview,cropped_image) + return preview # converts Image to base64 string def convert_image_to_base64(image): diff --git a/webui/flet/webui_flet.py b/webui/flet/webui_flet.py index ed066a8..b7e4b0f 100644 --- a/webui/flet/webui_flet.py +++ b/webui/flet/webui_flet.py @@ -7,7 +7,7 @@ from math import pi from typing import Optional from loguru import logger import logging -logging.basicConfig(level=logging.DEBUG) +#logging.basicConfig(level=logging.DEBUG) # utils imports from scripts import flet_utils @@ -110,6 +110,7 @@ def main(page: ft.Page): # property manager page.property_manager = property_manager + page.preview_height = 200 # settings def load_settings():