summaryrefslogtreecommitdiff
path: root/__init__.py
blob: 662816100b8b771b6a0be8ef8903211aeb0fe1c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# 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 # uses os and shutil modules

# 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():
        numpy_path = path + "/numpy"
        numpy_bad_path = path + "/numpy_bad"
        # rename the existing numpy folder to numpy bad and install newer numpy
        if (("2.79" in path) and ("site-packages" in path)
            and (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()