From 3663e978fff241ff0ca8369aaef21b0d2b2a32e7 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sun, 25 Sep 2022 16:20:36 -0400 Subject: [PATCH 1/6] Move Troubleshooting and History into panels --- __init__.py | 9 +-- classes.py | 12 ++-- operators/help_panel.py | 21 ------- operators/view_history.py | 30 ---------- ui/panel.py | 113 ++++++++++++++++++++++++++++---------- 5 files changed, 94 insertions(+), 91 deletions(-) delete mode 100644 operators/help_panel.py diff --git a/__init__.py b/__init__.py index 6945ec7c..12fa3959 100644 --- a/__init__.py +++ b/__init__.py @@ -16,17 +16,16 @@ "author": "Carson Katri, Greg Richardson, Kevin C. Burke", "description": "Use Stable Diffusion to generate unique textures straight from the shader editor.", "warning": "Requires installation of Stable Diffusion model weights", - "blender": (2, 80, 0), - "version": (0, 0, 5), + "blender": (3, 0, 0), + "version": (0, 0, 6), "location": "", "warning": "", - "category": "Node" + "category": "Paint" } import bpy from bpy.props import IntProperty, PointerProperty, EnumProperty import sys -import importlib from .help_section import register_section_props @@ -67,6 +66,8 @@ def register(): for tool in TOOLS: bpy.utils.register_tool(tool) + print(CLASSES) + def unregister(): for cls in PREFERENCE_CLASSES: bpy.utils.unregister_class(cls) diff --git a/classes.py b/classes.py index 5807c9b5..7acd8541 100644 --- a/classes.py +++ b/classes.py @@ -1,24 +1,22 @@ from .operators.install_dependencies import InstallDependencies from .operators.open_latest_version import OpenLatestVersion from .operators.dream_texture import DreamTexture, ReleaseGenerator -from .operators.help_panel import HelpPanel -from .operators.view_history import RecallHistoryEntry, SCENE_UL_HistoryList, ViewHistory +from .operators.view_history import RecallHistoryEntry, SCENE_UL_HistoryList from .operators.inpaint_area_brush import InpaintAreaStroke from .property_groups.dream_prompt import DreamPrompt -from .ui.panel import DREAM_PT_dream_panel, DREAM_PT_dream_node_panel +from .ui.panel import panels, history_panels, troubleshooting_panels from .preferences import OpenGitDownloads, OpenHuggingFace, OpenWeightsDirectory, OpenRustInstaller, ValidateInstallation, StableDiffusionPreferences CLASSES = ( DreamTexture, ReleaseGenerator, - HelpPanel, OpenLatestVersion, - ViewHistory, RecallHistoryEntry, InpaintAreaStroke, SCENE_UL_HistoryList, - DREAM_PT_dream_panel, - DREAM_PT_dream_node_panel, + *panels(), + *history_panels(), + *troubleshooting_panels(), ) PREFERENCE_CLASSES = ( diff --git a/operators/help_panel.py b/operators/help_panel.py deleted file mode 100644 index d4603c06..00000000 --- a/operators/help_panel.py +++ /dev/null @@ -1,21 +0,0 @@ -import bpy -from ..help_section import help_section - -class HelpPanel(bpy.types.Operator): - bl_idname = "shade.dream_textures_help" - bl_label = "Troubleshoot" - bl_description = "Find fixes to some common issues" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - return True - - def invoke(self, context, event): - return context.window_manager.invoke_props_dialog(self, width=500) - - def draw(self, context): - help_section(self.layout, context) - - def execute(self, context): - return {"FINISHED"} \ No newline at end of file diff --git a/operators/view_history.py b/operators/view_history.py index 7a907f02..f705f0fe 100644 --- a/operators/view_history.py +++ b/operators/view_history.py @@ -1,35 +1,6 @@ import bpy from ..property_groups.dream_prompt import sampler_options from ..preferences import StableDiffusionPreferences - -class ViewHistory(bpy.types.Operator): - bl_idname = "shade.dream_textures_history" - bl_label = "History" - bl_description = "View and reload previous prompts" - bl_options = {'REGISTER'} - - selection: bpy.props.IntProperty(name="Selection") - - @classmethod - def poll(self, context): - return True - - def invoke(self, context, event): - return context.window_manager.invoke_props_dialog(self, width=500) - - def draw(self, context): - # split = self.layout.split(factor=0.95) - # header = split.row() - header = self.layout.row() - header.label(text="Subject") - header.label(text="Size") - header.label(text="Steps") - header.label(text="Sampler") - self.layout.template_list("SCENE_UL_HistoryList", "", context.preferences.addons[StableDiffusionPreferences.bl_idname].preferences, "history", context.scene, "dream_textures_history_selection") - self.layout.operator(RecallHistoryEntry.bl_idname) - - def execute(self, context): - return {"FINISHED"} class SCENE_UL_HistoryList(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): @@ -57,6 +28,5 @@ def execute(self, context): for prop in selection.__annotations__.keys(): if hasattr(context.scene.dream_textures_prompt, prop): setattr(context.scene.dream_textures_prompt, prop, getattr(selection, prop)) - bpy.ops.shade.dream_texture('INVOKE_DEFAULT') return {"FINISHED"} \ No newline at end of file diff --git a/ui/panel.py b/ui/panel.py index af329400..1115001d 100644 --- a/ui/panel.py +++ b/ui/panel.py @@ -3,9 +3,12 @@ from ..pil_to_image import * from ..prompt_engineering import * from ..operators.dream_texture import DreamTexture, image_has_alpha, ReleaseGenerator -from ..operators.view_history import ViewHistory +from ..operators.view_history import SCENE_UL_HistoryList, RecallHistoryEntry from ..operators.open_latest_version import OpenLatestVersion, new_version_available -from ..operators.help_panel import HelpPanel +from ..help_section import help_section +from ..preferences import StableDiffusionPreferences + +SPACE_TYPES = {'IMAGE_EDITOR', 'NODE_EDITOR'} def draw_panel(self, context): layout = self.layout @@ -68,10 +71,6 @@ def draw_panel(self, context): advanced_box.prop(scene.dream_textures_prompt, "sampler") advanced_box.prop(scene.dream_textures_prompt, "show_steps") - row = layout.row() - row.operator(ViewHistory.bl_idname, icon="RECOVER_LAST") - row.operator(HelpPanel.bl_idname, icon="QUESTION", text="") - row.operator(ReleaseGenerator.bl_idname, icon="X", text="") row = layout.row() row.scale_y = 1.5 if context.scene.dream_textures_progress <= 0: @@ -80,26 +79,82 @@ def draw_panel(self, context): else: row.operator(DreamTexture.bl_idname, icon="PLAY", text="Generate") else: - row.prop(context.scene, 'dream_textures_progress', slider=True) - row.enabled = False - -class DREAM_PT_dream_panel(Panel): - """Creates a Panel in the scene context of the properties editor""" - bl_label = "Dream Texture" - bl_category = "Dream" - bl_idname = "DREAM_PT_dream_panel" - bl_space_type = 'IMAGE_EDITOR' - bl_region_type = 'UI' - - def draw(self, context): - draw_panel(self, context) - -class DREAM_PT_dream_node_panel(Panel): - bl_idname = "DREAM_PT_dream_node_panel" - bl_label = "Dream Texture" - bl_category = "Dream" - bl_space_type = 'NODE_EDITOR' - bl_region_type = 'UI' - - def draw(self, context): - draw_panel(self, context) \ No newline at end of file + disabled_row = row.row() + disabled_row.prop(context.scene, 'dream_textures_progress', slider=True) + disabled_row.enabled = False + row.operator(ReleaseGenerator.bl_idname, icon="X", text="") + +def panels(): + for space_type in SPACE_TYPES: + class DreamTexturePanel(Panel): + """Creates a Panel in the scene context of the properties editor""" + bl_label = "Dream Texture" + bl_category = "Dream" + bl_idname = f"DREAM_PT_dream_panel_{space_type}" + bl_space_type = space_type + bl_region_type = 'UI' + + @classmethod + def poll(self, context): + if self.bl_space_type == 'NODE_EDITOR': + return context.area.ui_type == "ShaderNodeTree" or context.area.ui_type == "CompositorNodeTree" + else: + return True + + def draw(self, context): + draw_panel(self, context) + DreamTexturePanel.__name__ = f"DREAM_PT_dream_panel_{space_type}" + yield DreamTexturePanel + +def history_panels(): + for space_type in SPACE_TYPES: + class HistoryPanel(Panel): + """Panel for Dream Textures History""" + bl_label = "History" + bl_category = "Dream" + bl_idname = f"DREAM_PT_dream_history_panel_{space_type}" + bl_space_type = space_type + bl_region_type = 'UI' + + selection: bpy.props.IntProperty(name="Selection") + + @classmethod + def poll(self, context): + if self.bl_space_type == 'NODE_EDITOR': + return context.area.ui_type == "ShaderNodeTree" or context.area.ui_type == "CompositorNodeTree" + else: + return True + + def draw(self, context): + header = self.layout.row() + header.label(text="Subject") + header.label(text="Size") + header.label(text="Steps") + header.label(text="Sampler") + self.layout.template_list("SCENE_UL_HistoryList", "", context.preferences.addons[StableDiffusionPreferences.bl_idname].preferences, "history", context.scene, "dream_textures_history_selection") + self.layout.operator(RecallHistoryEntry.bl_idname) + HistoryPanel.__name__ = f"DREAM_PT_dream_history_panel_{space_type}" + yield HistoryPanel + +def troubleshooting_panels(): + for space_type in SPACE_TYPES: + class TroubleshootingPanel(Panel): + """Panel for Dream Textures Troubleshooting""" + bl_label = "Troubleshooting" + bl_category = "Dream" + bl_idname = f"DREAM_PT_dream_troubleshooting_panel_{space_type}" + bl_space_type = space_type + bl_region_type = 'UI' + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(self, context): + if self.bl_space_type == 'NODE_EDITOR': + return context.area.ui_type == "ShaderNodeTree" or context.area.ui_type == "CompositorNodeTree" + else: + return True + + def draw(self, context): + help_section(self.layout, context) + TroubleshootingPanel.__name__ = f"DREAM_PT_dream_troubleshooting_panel_{space_type}" + yield TroubleshootingPanel \ No newline at end of file From 310b2dfcac198ee37f4edf6ea78b5712a560ab0b Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sun, 25 Sep 2022 16:21:35 -0400 Subject: [PATCH 2/6] Update VERSION --- version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.py b/version.py index 6e3a1031..0eadb44b 100644 --- a/version.py +++ b/version.py @@ -1,4 +1,4 @@ -VERSION = (0, 0, 5) +VERSION = (0, 0, 6) def version_tag(version): return f"{version[0]}.{version[1]}.{version[2]}" From 82a94ab179f75965004b00131a3826a7cd576df7 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sun, 25 Sep 2022 16:24:48 -0400 Subject: [PATCH 3/6] Fix version checking --- __init__.py | 2 -- ui/panel.py | 2 +- version.py | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/__init__.py b/__init__.py index 12fa3959..bd384c75 100644 --- a/__init__.py +++ b/__init__.py @@ -66,8 +66,6 @@ def register(): for tool in TOOLS: bpy.utils.register_tool(tool) - print(CLASSES) - def unregister(): for cls in PREFERENCE_CLASSES: bpy.utils.unregister_class(cls) diff --git a/ui/panel.py b/ui/panel.py index 1115001d..35d31506 100644 --- a/ui/panel.py +++ b/ui/panel.py @@ -13,7 +13,7 @@ def draw_panel(self, context): layout = self.layout scene = context.scene - + if new_version_available(): layout.operator(OpenLatestVersion.bl_idname, icon="IMPORT") diff --git a/version.py b/version.py index 0eadb44b..35932bf4 100644 --- a/version.py +++ b/version.py @@ -3,4 +3,4 @@ def version_tag(version): return f"{version[0]}.{version[1]}.{version[2]}" def version_tuple(tag): - return tuple(int(tag.split('.'))) + return tuple(map(lambda x: int(x), tag.split('.'))) From fe6dc14a2a871bd20288f1021bee4e4bb0ff2769 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sun, 25 Sep 2022 16:26:10 -0400 Subject: [PATCH 4/6] Remove concept artist picker --- prompt_engineering.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/prompt_engineering.py b/prompt_engineering.py index ea047814..8c9dda2f 100644 --- a/prompt_engineering.py +++ b/prompt_engineering.py @@ -98,16 +98,6 @@ def photography_prompt(tokens): ('vehicle', 'Vehicle'), )) -concept_artist_token = PromptToken('concept_artist', 'Concept Artist', ( - ('blevins', 'Neil Blevins'), - ('grimmer', 'Jordan Grimmer'), - ('mullins', 'Craig Mullins'), - ('rutkowski', 'Greg Rutkowski'), - ('shinkai', 'Makoto Shinkai'), - ('simonetti', 'Mark Simonetti'), - ('stalenhag', 'Simon Stalenhag'), -)) - genre_token = PromptToken('genre', 'Genre', ( ('scifi', 'Sci-Fi'), ('fantasy', 'Fantasy'), @@ -116,12 +106,12 @@ def photography_prompt(tokens): )) def concept_art_prompt(tokens): - return f"{tokens.subject}, {tokens.subject_type} concept art, {tokens.genre} digital painting, by {tokens.concept_artist}, trending on ArtStation" + return f"{tokens.subject}, {tokens.subject_type} concept art, {tokens.genre} digital painting, trending on ArtStation" concept_art_structure = PromptStructure( 'concept_art', 'Concept Art', - (subject_token, subject_type_token, genre_token, concept_artist_token), + (subject_token, subject_type_token, genre_token), concept_art_prompt ) From 3d204dd8bb5f894a4e4de0aa4e047db78161a497 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sun, 25 Sep 2022 16:46:17 -0400 Subject: [PATCH 5/6] Fix issue with inpaint/init image toggling --- generator_process.py | 4 ++-- operators/dream_texture.py | 9 +-------- property_groups/dream_prompt.py | 3 ++- ui/panel.py | 29 ++++++++++++++++------------- 4 files changed, 21 insertions(+), 24 deletions(-) diff --git a/generator_process.py b/generator_process.py index 3f8383c3..eaf9d9d3 100644 --- a/generator_process.py +++ b/generator_process.py @@ -198,8 +198,8 @@ def view_step(samples, step): return # stdin closed args = json.loads(stdin.read(json_len)) - if generator is None or generator.full_precision != args['full_precision']: - writeInfo("Initializing Generator") + if generator is None or (generator.full_precision != args['full_precision'] and sys.platform != 'darwin'): + writeInfo("Loading Model") try: generator = Generate( conf=models_config, diff --git a/operators/dream_texture.py b/operators/dream_texture.py index 7a62cb70..4202b014 100644 --- a/operators/dream_texture.py +++ b/operators/dream_texture.py @@ -20,13 +20,6 @@ last_data_block = None timer = None -def image_has_alpha(img): - b = 32 if img.is_float else 8 - return ( - img.depth == 2*b or # Grayscale+Alpha - img.depth == 4*b # RGB+Alpha - ) - class DreamTexture(bpy.types.Operator): bl_idname = "shade.dream_texture" bl_label = "Dream Texture" @@ -162,7 +155,7 @@ def save_temp_image(img, path=None): if scene.dream_textures_prompt.use_inpainting: for area in screen.areas: if area.type == 'IMAGE_EDITOR': - if area.spaces.active.image is not None and image_has_alpha(area.spaces.active.image): + if area.spaces.active.image is not None: init_img = area.spaces.active.image init_img_path = None if init_img is not None: diff --git a/property_groups/dream_prompt.py b/property_groups/dream_prompt.py index 8bba8704..9eb66889 100644 --- a/property_groups/dream_prompt.py +++ b/property_groups/dream_prompt.py @@ -1,6 +1,7 @@ import bpy from bpy.props import FloatProperty, IntProperty, EnumProperty, BoolProperty, StringProperty, PointerProperty from ..prompt_engineering import * +import sys sampler_options = [ ("ddim", "DDIM", "", 1), @@ -37,7 +38,7 @@ def seed_clamp(self, ctx): "show_advanced": BoolProperty(name="", default=False), "random_seed": BoolProperty(name="Random Seed", default=True, description="Randomly pick a seed"), "seed": StringProperty(name="Seed", default="0", description="Manually pick a seed", update=seed_clamp), - "full_precision": BoolProperty(name="Full Precision", default=False, description="Whether to use full precision or half precision floats. Full precision is slower, but required by some GPUs"), + "full_precision": BoolProperty(name="Full Precision", default=True if sys.platform == 'darwin' else False, description="Whether to use full precision or half precision floats. Full precision is slower, but required by some GPUs"), "iterations": IntProperty(name="Iterations", default=1, min=1, description="How many images to generate"), "steps": IntProperty(name="Steps", default=25, min=1), "cfg_scale": FloatProperty(name="CFG Scale", default=7.5, min=1, description="How strongly the prompt influences the image"), diff --git a/ui/panel.py b/ui/panel.py index 35d31506..99e3b825 100644 --- a/ui/panel.py +++ b/ui/panel.py @@ -2,18 +2,19 @@ from bpy.types import Panel from ..pil_to_image import * from ..prompt_engineering import * -from ..operators.dream_texture import DreamTexture, image_has_alpha, ReleaseGenerator +from ..operators.dream_texture import DreamTexture, ReleaseGenerator from ..operators.view_history import SCENE_UL_HistoryList, RecallHistoryEntry from ..operators.open_latest_version import OpenLatestVersion, new_version_available from ..help_section import help_section from ..preferences import StableDiffusionPreferences +import sys SPACE_TYPES = {'IMAGE_EDITOR', 'NODE_EDITOR'} def draw_panel(self, context): layout = self.layout scene = context.scene - + if new_version_available(): layout.operator(OpenLatestVersion.bl_idname, icon="IMPORT") @@ -36,16 +37,17 @@ def draw_panel(self, context): size_box.prop(scene.dream_textures_prompt, "height") size_box.prop(scene.dream_textures_prompt, "seamless") - for area in context.screen.areas: - if area.type == 'IMAGE_EDITOR': - if area.spaces.active.image is not None and image_has_alpha(area.spaces.active.image): - inpainting_box = layout.box() - inpainting_heading = inpainting_box.row() - inpainting_heading.prop(scene.dream_textures_prompt, "use_inpainting") - inpainting_heading.label(text="Inpaint Open Image") - break - - if not scene.dream_textures_prompt.use_inpainting: + if not scene.dream_textures_prompt.use_init_img: + for area in context.screen.areas: + if area.type == 'IMAGE_EDITOR': + if area.spaces.active.image is not None: + inpainting_box = layout.box() + inpainting_heading = inpainting_box.row() + inpainting_heading.prop(scene.dream_textures_prompt, "use_inpainting") + inpainting_heading.label(text="Inpaint Open Image") + break + + if not scene.dream_textures_prompt.use_inpainting or area.spaces.active.image is None: init_img_box = layout.box() init_img_heading = init_img_box.row() init_img_heading.prop(scene.dream_textures_prompt, "use_init_img") @@ -60,7 +62,8 @@ def draw_panel(self, context): advanced_box_heading.prop(scene.dream_textures_prompt, "show_advanced", icon="DOWNARROW_HLT" if scene.dream_textures_prompt.show_advanced else "RIGHTARROW_THIN", emboss=False, icon_only=True) advanced_box_heading.label(text="Advanced Configuration") if scene.dream_textures_prompt.show_advanced: - advanced_box.prop(scene.dream_textures_prompt, "full_precision") + if sys.platform not in {'darwin'}: + advanced_box.prop(scene.dream_textures_prompt, "full_precision") advanced_box.prop(scene.dream_textures_prompt, "random_seed") seed_row = advanced_box.row() seed_row.prop(scene.dream_textures_prompt, "seed") From 40a9e451bff28299ebd12f691c886c84c0ce9557 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Sun, 25 Sep 2022 17:07:08 -0400 Subject: [PATCH 6/6] Improve history header --- operators/view_history.py | 16 +++++++++++----- ui/panel.py | 10 +++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/operators/view_history.py b/operators/view_history.py index f705f0fe..07ac3fce 100644 --- a/operators/view_history.py +++ b/operators/view_history.py @@ -5,10 +5,16 @@ class SCENE_UL_HistoryList(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname): if self.layout_type in {'DEFAULT', 'COMPACT'}: - layout.label(text=item.get_prompt_subject(), translate=False, icon_value=icon) - layout.label(text=f"{item.width}x{item.height}", translate=False) - layout.label(text=f"{item.steps} steps", translate=False) - layout.label(text=next(x for x in sampler_options if x[0] == item.sampler)[1], translate=False) + if item.prompt_structure_token_subject == "SCENE_UL_HistoryList_header": + layout.label(text="Subject") + layout.label(text="Size") + layout.label(text="Steps") + layout.label(text="Sampler") + else: + layout.label(text=item.get_prompt_subject(), translate=False, icon_value=icon) + layout.label(text=f"{item.width}x{item.height}", translate=False) + layout.label(text=f"{item.steps} steps", translate=False) + layout.label(text=next(x for x in sampler_options if x[0] == item.sampler)[1], translate=False) elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) @@ -21,7 +27,7 @@ class RecallHistoryEntry(bpy.types.Operator): @classmethod def poll(self, context): - return context.scene.dream_textures_history_selection is not None + return context.scene.dream_textures_history_selection is not None and context.scene.dream_textures_history_selection > 0 def execute(self, context): selection = context.preferences.addons[StableDiffusionPreferences.bl_idname].preferences.history[context.scene.dream_textures_history_selection] diff --git a/ui/panel.py b/ui/panel.py index 99e3b825..4ad48563 100644 --- a/ui/panel.py +++ b/ui/panel.py @@ -129,11 +129,11 @@ def poll(self, context): return True def draw(self, context): - header = self.layout.row() - header.label(text="Subject") - header.label(text="Size") - header.label(text="Steps") - header.label(text="Sampler") + if len(context.preferences.addons[StableDiffusionPreferences.bl_idname].preferences.history) < 1: + header = context.preferences.addons[StableDiffusionPreferences.bl_idname].preferences.history.add() + else: + header = context.preferences.addons[StableDiffusionPreferences.bl_idname].preferences.history[0] + header.prompt_structure_token_subject = "SCENE_UL_HistoryList_header" self.layout.template_list("SCENE_UL_HistoryList", "", context.preferences.addons[StableDiffusionPreferences.bl_idname].preferences, "history", context.scene, "dream_textures_history_selection") self.layout.operator(RecallHistoryEntry.bl_idname) HistoryPanel.__name__ = f"DREAM_PT_dream_history_panel_{space_type}"