diff --git a/.vscode/settings.json b/.vscode/settings.json index 936a8a6..b3f4f67 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,4 +12,5 @@ "python.analysis.extraPaths": [ "blender_autocomplete" ], + "python.pythonPath": "/home/albert/anaconda3/bin/python", } \ No newline at end of file diff --git a/addon/panel/__init__.py b/addon/panel/__init__.py index 71e54da..8af9f01 100644 --- a/addon/panel/__init__.py +++ b/addon/panel/__init__.py @@ -3,12 +3,16 @@ from .measures_circular_panel import MEASURES_PT_CIRCULAR_PANEL classes = [ - MEASURES_PT_MAINPANEL, MEASURES_PT_CIRCULAR_PANEL, MEASURES_PT_GEODESIC_PANEL ] +def register_main_panel(): + from bpy.utils import register_class + register_class(MEASURES_PT_MAINPANEL) + + def register_panels(): from bpy.utils import register_class for cls in classes: @@ -19,3 +23,8 @@ def unregister_panels(): from bpy.utils import unregister_class for cls in reversed(classes): unregister_class(cls) + + +def unregister_main_panel(): + from bpy.utils import unregister_class + unregister_class(MEASURES_PT_MAINPANEL) diff --git a/addon/panel/measures_geodesic_panel.py b/addon/panel/measures_geodesic_panel.py index 65640b4..6ab54ce 100644 --- a/addon/panel/measures_geodesic_panel.py +++ b/addon/panel/measures_geodesic_panel.py @@ -1,4 +1,6 @@ -from ..register.dependency_flag import are_dependencies_installed +from ..register.dependency_handling import \ + are_dependencies_installed, show_no_dependencies_warning + import bpy @@ -16,12 +18,6 @@ def draw(self, context): layout = self.layout layout.scale_y = 1.2 - if are_dependencies_installed(): - self.show_operator(layout) - else: - self.show_no_dependencies_warning(layout) - - def show_operator(self, layout): row = layout.row() row.label( text="Select a origin and destiny to generate a path", @@ -29,22 +25,3 @@ def show_operator(self, layout): ) row = layout.row() row.operator('measures.create_geodesic') - - def show_no_dependencies_warning(self, layout): - - lines = [f"Please install the missing dependencies for the Measures add-on.", - f"1. Open the preferences (Edit > Preferences > Add-ons).", - f"2. Search for the Measures Library add-on.", - f"3. Open the details section of the add-on.", - f"4. Click on the Install Dependencies button.", - f" This will download and install the missing Python packages, if Blender has the required", - f" permissions.", - f"If you're attempting to run the add-on from the text editor, you won't see the options described", - f"above. Please install the add-on properly through the preferences.", - f"1. Open the add-on preferences (Edit > Preferences > Add-ons).", - f"2. Press the \"Install\" button.", - f"3. Search for the add-on file.", - f"4. Confirm the selection by pressing the \"Install Add-on\" button in the file browser."] - - for line in lines: - layout.label(text=line) diff --git a/addon/panel/measures_main_panel.py b/addon/panel/measures_main_panel.py index 44c774b..acf2ef7 100644 --- a/addon/panel/measures_main_panel.py +++ b/addon/panel/measures_main_panel.py @@ -1,3 +1,6 @@ +from ..register.dependency_handling import \ + are_dependencies_installed, show_no_dependencies_warning + import bpy @@ -15,6 +18,9 @@ def draw(self, context): layout = self.layout layout.scale_y = 1.2 + if not are_dependencies_installed(): + show_no_dependencies_warning(layout) + # row = layout.row() # row.label(text="Adjust the plane to the Avatar", icon="MOD_TINT") diff --git a/addon/preferences/__init__.py b/addon/preferences/__init__.py index f1d05f1..31d60ff 100644 --- a/addon/preferences/__init__.py +++ b/addon/preferences/__init__.py @@ -1,4 +1,6 @@ -from ..register.dependency_handling import MEASURES_OT_Install_Dependencies +from ..preferences.install_dependencies_operator import \ + MEASURES_OT_Install_Dependencies + from .addon import MEASURES_Props from .color import MEASURES_Color from .settings import MEASURES_Settings diff --git a/addon/preferences/addon.py b/addon/preferences/addon.py index 3cfda15..d0c82b0 100644 --- a/addon/preferences/addon.py +++ b/addon/preferences/addon.py @@ -1,5 +1,8 @@ -from ..register.dependency_handling import MEASURES_OT_Install_Dependencies import bpy + +from .install_dependencies_operator import \ + MEASURES_OT_Install_Dependencies + from ..utility.addon import addon_name, get_prefs from bpy.props import PointerProperty diff --git a/addon/preferences/install_dependencies_operator.py b/addon/preferences/install_dependencies_operator.py new file mode 100644 index 0000000..75d4792 --- /dev/null +++ b/addon/preferences/install_dependencies_operator.py @@ -0,0 +1,40 @@ +import subprocess +from ..register.dependency_handling import \ + are_dependencies_installed, get_dependencies,\ + install_and_import_module, install_pip, set_dependency_installed_flag + +from ..register import register_dependent_objects + +import bpy + + +class MEASURES_OT_Install_Dependencies(bpy.types.Operator): + bl_idname = "measures.install_dependencies" + bl_label = "Install dependencies" + bl_description = ("Downloads and installs the required python packages for this add-on. " + "Internet connection is required. Blender may have to be started with " + "elevated permissions in order to install the package") + bl_options = {"REGISTER", "INTERNAL"} + + @classmethod + def poll(self, context): + # Deactivate when dependencies have been installed + return not are_dependencies_installed() + + def execute(self, context): + try: + install_pip() + for dependency in get_dependencies(): + install_and_import_module(module_name=dependency.module, + package_name=dependency.package, + global_name=dependency.name) + except (subprocess.CalledProcessError, ImportError) as err: + self.report({"ERROR"}, str(err)) + return {"CANCELLED"} + + set_dependency_installed_flag(True) + + # Register the panels, operators, etc. since dependencies are installed + register_dependent_objects() + + return {"FINISHED"} diff --git a/addon/register/__init__.py b/addon/register/__init__.py index de2e6fd..bf395f1 100644 --- a/addon/register/__init__.py +++ b/addon/register/__init__.py @@ -1,4 +1,5 @@ from ..register.dependency_handling import \ + are_dependencies_installed, \ import_dependencies, \ set_dependency_installed_flag @@ -11,27 +12,18 @@ def register_addon(): from ..preferences import register_preferences register_preferences() + # Main panel + from ..panel import register_main_panel + register_main_panel() + try: import_dependencies() set_dependency_installed_flag(True) except ModuleNotFoundError: print("Dependencies were not installed...") + return - # Menus - # from ..menu import register_menus - # register_menus() - - # Panels - from ..panel import register_panels - register_panels() - - # Operators - from ..operator import register_operators - register_operators() - - # Keymaps - # from .keymap import register_keymap - # register_keymap() + register_dependent_objects() def unregister_addon(): @@ -40,6 +32,12 @@ def unregister_addon(): from ..preferences import unregister_preferences unregister_preferences() + from ..panel import unregister_main_panel + unregister_main_panel() + + if not are_dependencies_installed(): + return + # Menus # from ..menu import unregister_menus # unregister_menus() @@ -55,3 +53,21 @@ def unregister_addon(): # Keymaps # from .keymap import unregister_keymap # unregister_keymap() + + +def register_dependent_objects(): + # Menus + # from ..menu import register_menus + # register_menus() + + # Panels + from ..panel import register_panels + register_panels() + + # Operators + from ..operator import register_operators + register_operators() + + # Keymaps + # from .keymap import register_keymap + # register_keymap() diff --git a/addon/register/dependency_flag.py b/addon/register/dependency_flag.py deleted file mode 100644 index 4ed9e88..0000000 --- a/addon/register/dependency_flag.py +++ /dev/null @@ -1,11 +0,0 @@ -global dependencies_installed - - -def set_dependency_installed_flag(flag: bool): - global dependencies_installed - dependencies_installed = flag - - -def are_dependencies_installed() -> bool: - global dependencies_installed - return dependencies_installed diff --git a/addon/register/dependency_handling.py b/addon/register/dependency_handling.py index 5764933..70b1105 100644 --- a/addon/register/dependency_handling.py +++ b/addon/register/dependency_handling.py @@ -1,7 +1,5 @@ -from .dependency_flag import are_dependencies_installed, set_dependency_installed_flag from collections import namedtuple from typing import Tuple -import bpy import subprocess import sys import os @@ -17,34 +15,21 @@ dependencies: Tuple[Dependency] = (Dependency(module="potpourri3d", package=None, name=None),) +global dependencies_installed -class MEASURES_OT_Install_Dependencies(bpy.types.Operator): - bl_idname = "measures.install_dependencies" - bl_label = "Install dependencies" - bl_description = ("Downloads and installs the required python packages for this add-on. " - "Internet connection is required. Blender may have to be started with " - "elevated permissions in order to install the package") - bl_options = {"REGISTER", "INTERNAL"} - @classmethod - def poll(self, context): - # Deactivate when dependencies have been installed - return not are_dependencies_installed() +def set_dependency_installed_flag(flag: bool): + global dependencies_installed + dependencies_installed = flag - def execute(self, context): - try: - install_pip() - for dependency in dependencies: - install_and_import_module(module_name=dependency.module, - package_name=dependency.package, - global_name=dependency.name) - except (subprocess.CalledProcessError, ImportError) as err: - self.report({"ERROR"}, str(err)) - return {"CANCELLED"} - set_dependency_installed_flag(True) +def are_dependencies_installed() -> bool: + global dependencies_installed + return dependencies_installed - return {"FINISHED"} + +def get_dependencies(): + return dependencies def import_dependencies(): @@ -125,4 +110,24 @@ def install_and_import_module(module_name, package_name=None, global_name=None): subprocess.run([sys.executable, "-m", "pip", "install", package_name], check=True, env=environ_copy) # The installation succeeded, attempt to import the module again - import_module(module_name, global_name) \ No newline at end of file + import_module(module_name, global_name) + + +def show_no_dependencies_warning(layout): + + lines = [f"Please install the missing dependencies for the Measures add-on.", + f"1. Open the preferences (Edit > Preferences > Add-ons).", + f"2. Search for the Measures Library add-on.", + f"3. Open the details section of the add-on.", + f"4. Click on the Install Dependencies button.", + f" This will download and install the missing Python packages, if Blender has the required", + f" permissions.", + f"If you're attempting to run the add-on from the text editor, you won't see the options described", + f"above. Please install the add-on properly through the preferences.", + f"1. Open the add-on preferences (Edit > Preferences > Add-ons).", + f"2. Press the \"Install\" button.", + f"3. Search for the add-on file.", + f"4. Confirm the selection by pressing the \"Install Add-on\" button in the file browser."] + + for line in lines: + layout.label(text=line)