# references # https://s-nako.work/2020/09/blender-error-attributeerror-_restrictcontext-object-has-no-attribute-view_layer/ # https://web.archive.org/web/20210925181415/https://blenderbrew.com/custom-application-templates-in-blender/ # elemental python modules blenxy needs # that the python interpreter must have built in import bpy, importlib, sys, subprocess, os, shutil import math, mathutils, warnings, struct, site from . import file_ops # elemental python modules blenxy needs # that the python interpreter probably does not have built in/needs to be updated pip_modules = ["pip", "wheel", "setuptools"] new_modules = ["lxml", "numpy"] # check which of the new modules needs to be installed def new_mod_check(mod_names): # variable to return rtn = [] # traverse into all the new_modules for mod_name in mod_names: # skip numpy if the numpy_bad folder was created if (mod_name == "numpy"): for path in site.getsitepackages(): if ("2.79" in path): numpy_path = path + "/numpy" numpy_bad_path = path + "/numpy_bad" # rename the existing numpy folder to numpy bad and install newer numpy if (file_ops.f_exists(numpy_bad_path) == False): file_ops.rename(numpy_path, numpy_bad_path) rtn.append("numpy") break continue # try importing the module try: importlib.import_module(mod_name) except: rtn.append(mod_name) # done! return rtn # install given modules with pip but be sure to have pip first def new_mod_install(mod_names): # get python's interpreter binary path py_bin = bpy.app.binary_path_python pip_install = [py_bin, "-B", "-m", "pip", "install", "--trusted-host", "pypi.python.org", "--trusted-host", "files.pythonhosted.org", "--trusted-host", "pypi.org", "-U", "--force-reinstall", "--only-binary", ":all:"] # check if the pip module is available try: importlib.import_module("pip") except: # install pip subprocess.run([py_bin, "-B", "-m", "ensurepip"]) subprocess.run(pip_install + pip_modules) # install the rest of the modules if (mod_names != []): for mod_name in mod_names: # normal module installation subprocess.run(pip_install + [mod_name]) return True return False # all blenxy custom modules blenxy_modules = ["basic_settings", # user settings blenxy has "collada_superbmd_import", # custom importer for SuperBMD collada files "collada_superbmd_export", # custom exporter for SuperBMD collada files "obj_kcl_export", # custom exporter for OBJ files (collision) "obj_neokclcreate_import", # custom importer for OBJ files (collision, NeoKCLCreate) "bck_import", # custom importer for SMG BCK files "bck_export"] # custom exporter for SMG BCK files # function used to refresh blenxy's custom modules # so that they can be updated without closing blender @bpy.app.handlers.persistent def unload_blenxy_stuff(dummy): # execute the unregister functions from each module # these functions won't die if the stuff to unregister isn't there for mod_name in blenxy_modules: mod = importlib.import_module("." + mod_name, __package__) mod.unregister() # reload the modules in case they were modified (dev stuff) for mod_name in blenxy_modules: mod = importlib.import_module("." + mod_name, __package__) importlib.reload(mod) # register function that blender will call when the template is loaded def register(): # print the welcome print("\nWelcome to Blenxy!") print("Running on Blender: %s\n" % (bpy.app.version.__str__())) # checking python modules if (new_mod_install(new_mod_check(new_modules)) == True): print("New modules installed. Exiting...") exit(0) for mod_name in new_modules: mod = importlib.import_module(mod_name) print("%s %s is installed!" % (mod_name, mod.__version__)) # add this function to load_post first bpy.app.handlers.load_post.append(unload_blenxy_stuff) # add the register functions to load_post for mod_name in blenxy_modules: mod = importlib.import_module("." + mod_name, __package__) bpy.app.handlers.load_post.append(mod.register) # unregister function that blender will call when a new template is loaded def unregister(): # print the goodbye print("\nLeaving Blenxy!\n") # remove the stuff added to the load_post list bpy.app.handlers.load_post.remove(unload_blenxy_stuff) for mod_name in blenxy_modules: mod = importlib.import_module("." + mod_name, __package__) for func in bpy.app.handlers.load_post: if (mod.__name__ in func.__module__): bpy.app.handlers.load_post.remove(func) break # execute module's unregister functions for mod_name in blenxy_modules: mod = importlib.import_module("." + mod_name, __package__) mod.unregister()