From 789d29b0bc2586e6d31e743e56ca7ca60ba15b7a Mon Sep 17 00:00:00 2001 From: sercero Date: Sat, 23 Mar 2024 17:46:39 -0300 Subject: [PATCH] Fix several problems with loading and saving configuration, also improve reloading and use json --- README.md | 4 +-- io_ogre/__init__.py | 29 +++++++-------- io_ogre/api.py | 1 - io_ogre/config.py | 51 +++++++++++++++++---------- io_ogre/ogre/material.py | 20 +++-------- io_ogre/ogre/materialv2json.py | 16 --------- io_ogre/ogre/mesh.py | 21 ++--------- io_ogre/ogre/node_anim.py | 16 --------- io_ogre/ogre/ogre_import.py | 10 +++--- io_ogre/ogre/program.py | 10 ------ io_ogre/ogre/scene.py | 42 ++++++---------------- io_ogre/ogre/skeleton.py | 16 --------- io_ogre/ui/__init__.py | 24 ++++--------- io_ogre/ui/export.py | 64 +++++++++++++++------------------- io_ogre/ui/importer.py | 48 ++++++++++++------------- io_ogre/util.py | 14 ++------ 16 files changed, 126 insertions(+), 260 deletions(-) diff --git a/README.md b/README.md index 0d7cea8..947f9b7 100644 --- a/README.md +++ b/README.md @@ -50,8 +50,8 @@ There are two possible solutions: ## Updating to new versions ## -If you are upgrading from a previous version of blender2ogre and having problems, you may want to delete your old .pickle config file from -[$BLENDER_DIR](https://docs.blender.org/manual/en/latest/advanced/blender_directory_layout.html)`/config/scripts/blender2ogre.pickle` and restart blender. +If you are upgrading from a previous version of blender2ogre and having problems, you may want to delete your old .json config file from +[$BLENDER_DIR](https://docs.blender.org/manual/en/latest/advanced/blender_directory_layout.html)`/config/scripts/io_ogre.json` and restart blender. ## Video Tutorials * [General Usage](http://www.youtube.com/watch?feature=player_embedded&v=3EpwEsB0_kk) diff --git a/io_ogre/__init__.py b/io_ogre/__init__.py index c6922fc..c15cdbd 100644 --- a/io_ogre/__init__.py +++ b/io_ogre/__init__.py @@ -30,24 +30,19 @@ # https://blender.stackexchange.com/questions/28504/blender-ignores-changes-to-python-scripts/28505 # When bpy is already in local, we know this is not the initial import... if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib import importlib - if "config" in locals(): - importlib.reload(config) - if "properties" in locals(): - importlib.reload(properties) - if "ui" in locals(): - importlib.reload(ui) - -# This is only relevant on first run, on later reloads those modules -# are already in locals() and those statements do not do anything. -from . import config -from . import properties -from . import ui + #print("Reloading modules: config, mesh_preview, properties, xml, ui, util") + importlib.reload(config) + importlib.reload(mesh_preview) + importlib.reload(properties) + importlib.reload(xml) + importlib.reload(ui) + importlib.reload(util) +import bpy import os, sys, logging from pprint import pprint -import bpy +from . import config, properties, ui # Import the plugin directory and setup the plugin class Blender2OgreAddonPreferences(bpy.types.AddonPreferences): @@ -107,7 +102,7 @@ def register(): logging.basicConfig(stream=sys.stdout, level=logging.INFO, format='[%(levelname)5s] %(message)s', datefmt='%H:%M:%S') logging.info('Starting io_ogre %s', bl_info["version"]) - + # The UI modules define auto_register functions that # return classes that should be loaded by the plugin for clazz in ui.auto_register(True): @@ -120,10 +115,10 @@ def register(): def unregister(): logging.info('Unloading io_ogre %s', bl_info["version"]) - + # Save the config config.save_config() - + # Unregister classes for clazz in ui.auto_register(False): bpy.utils.unregister_class(clazz) diff --git a/io_ogre/api.py b/io_ogre/api.py index bc6b01a..ece5114 100644 --- a/io_ogre/api.py +++ b/io_ogre/api.py @@ -5,4 +5,3 @@ from .ogre.scene import dot_scene # import various functions that can be used to export objects - diff --git a/io_ogre/config.py b/io_ogre/config.py index 7fb69c0..38aa264 100644 --- a/io_ogre/config.py +++ b/io_ogre/config.py @@ -1,4 +1,4 @@ -import bpy, os, sys, logging, pickle, mathutils +import bpy, os, sys, logging, mathutils, json from pprint import pprint from bpy.props import * @@ -28,9 +28,11 @@ ] CONFIG_PATH = bpy.utils.user_resource('CONFIG', path='scripts', create=True) -CONFIG_FILENAME = 'io_ogre.pickle' +CONFIG_FILENAME = 'io_ogre.json' CONFIG_FILEPATH = os.path.join(CONFIG_PATH, CONFIG_FILENAME) +CONFIG = {} + _CONFIG_DEFAULTS_ALL = { # General 'SWAP_AXIS' : 'xz-y', @@ -74,7 +76,7 @@ 'ARRAY' : True, 'EXTREMITY_POINTS' : 0, 'GENERATE_EDGE_LISTS' : False, - 'GENERATE_TANGENTS' : "0", + 'GENERATE_TANGENTS' : '0', 'OPTIMISE_ANIMATIONS' : True, 'INTERFACE_TOGGLE': False, 'OPTIMISE_VERTEX_BUFFERS' : True, @@ -102,7 +104,8 @@ 'IMPORT_ANIMATIONS' : True, 'ROUND_FRAMES' : True, 'USE_SELECTED_SKELETON' : True, - 'IMPORT_SHAPEKEYS' : True + 'IMPORT_SHAPEKEYS' : True, + 'IMPORT_LOGGING' : False } _CONFIG_TAGS_ = 'OGRETOOLS_XML_CONVERTER OGRETOOLS_MESH_UPGRADER MESH_PREVIEWER IMAGE_MAGICK_CONVERT USER_MATERIALS SHADER_PROGRAMS'.split() @@ -148,15 +151,22 @@ ## PUBLIC API continues def load_config(): + global CONFIG + logger.info('Loading config: %s' % CONFIG_FILEPATH) config_dict = {} # Check if the config file exists and load it if os.path.isfile( CONFIG_FILEPATH ): try: - with open( CONFIG_FILEPATH, 'rb' ) as f: - config_dict = pickle.load( f ) - except: - logger.error('Can not read config from %s' % CONFIG_FILEPATH) + with open( os.path.join(CONFIG_FILEPATH), 'r' ) as f: + config_dict = json.load(f) + except EOFError: + logger.error('Config file: %s is empty' % CONFIG_FILEPATH) + except Exception as e: + logger.error('Can not read config from: %s' % CONFIG_FILEPATH) + logger.error('Exception: %s' % e) + else: + logger.error('Config file: %s does not exist' % CONFIG_FILEPATH) # Load default values from _CONFIG_DEFAULTS_ALL if they don't exist after loading config from file for tag in _CONFIG_DEFAULTS_ALL: @@ -196,9 +206,6 @@ def load_config(): return config_dict -# Global CONFIG dictionary -CONFIG = load_config() - def get(name, default=None): global CONFIG if name in CONFIG: @@ -207,26 +214,34 @@ def get(name, default=None): logger.error("Config option %s does not exist!" % name) return default +# Global CONFIG dictionary +CONFIG = load_config() + def update(**kwargs): - for k,v in kwargs.items(): - if k not in _CONFIG_DEFAULTS_ALL: - logger.warn("Trying to set CONFIG['%s'] = %s, but it is not a known config setting" % (k,v)) - CONFIG[k] = v + global CONFIG + for key,value in kwargs.items(): + if key not in _CONFIG_DEFAULTS_ALL: + logger.warn("Trying to set CONFIG['%s'] = %s, but it is not a known config setting" % (key, value)) + #print("update() :: key: %s, value: %s" % (key, value)) + CONFIG[key] = value save_config() def save_config(): global CONFIG + logger.info('Saving config to: %s' % CONFIG_FILEPATH) #for key in CONFIG: print( '%s = %s' %(key, CONFIG[key]) ) if os.path.isdir( CONFIG_PATH ): try: - with open( CONFIG_FILEPATH, 'wb' ) as f: - pickle.dump( CONFIG, f, -1 ) - except: + with open( os.path.join(CONFIG_FILEPATH), 'w' ) as f: + f.write(json.dumps(CONFIG, indent=4)) + except Exception as e: logger.error('Can not write to %s' % CONFIG_FILEPATH) + logger.error('Exception: %s' % e) else: logger.error('Config directory %s does not exist' % CONFIG_PATH) def update_from_addon_preference(context): + global CONFIG addon_preferences = context.preferences.addons["io_ogre"].preferences for key in _CONFIG_TAGS_: diff --git a/io_ogre/ogre/material.py b/io_ogre/ogre/material.py index b3d5587..aec6560 100644 --- a/io_ogre/ogre/material.py +++ b/io_ogre/ogre/material.py @@ -1,22 +1,10 @@ - # When bpy is already in local, we know this is not the initial import... if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib import importlib - if "config" in locals(): - importlib.reload(config) - if "util" in locals(): - importlib.reload(util) - if "shader" in locals(): - importlib.reload(shader) - if "report" in locals(): - importlib.reload(report) - if "program" in locals(): - importlib.reload(program) - -# This is only relevant on first run, on later reloads those modules -# are already in locals() and those statements do not do anything. -import logging, os, shutil, tempfile, math + #print("Reloading modules: shader") + importlib.reload(shader) + +import os, shutil, tempfile, math, logging from .. import config from .. import shader from .. import util diff --git a/io_ogre/ogre/materialv2json.py b/io_ogre/ogre/materialv2json.py index 15fe9b4..38420db 100644 --- a/io_ogre/ogre/materialv2json.py +++ b/io_ogre/ogre/materialv2json.py @@ -1,19 +1,3 @@ - -# When bpy is already in local, we know this is not the initial import... -if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib - import importlib - if "config" in locals(): - importlib.reload(config) - if "util" in locals(): - importlib.reload(util) - if "report" in locals(): - importlib.reload(report) - if "material" in locals(): - importlib.reload(material) - -# This is only relevant on first run, on later reloads those modules -# are already in locals() and those statements do not do anything. import logging, os, shutil, tempfile, json from .. import config from .. import util diff --git a/io_ogre/ogre/mesh.py b/io_ogre/ogre/mesh.py index 0f53472..51e3e9d 100644 --- a/io_ogre/ogre/mesh.py +++ b/io_ogre/ogre/mesh.py @@ -1,27 +1,10 @@ import os, time, sys, logging -import bmesh -import mathutils -import math - -# When bpy is already in local, we know this is not the initial import... -if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib - import importlib - if "report" in locals(): - importlib.reload(report) - if "material" in locals(): - importlib.reload(material) - if "util" in locals(): - importlib.reload(util) - if "xml" in locals(): - importlib.reload(xml) - if "skeleton.Skeleton" in locals(): - importlib.reload(skeleton.Skeleton) +import bmesh, mathutils, math from ..report import Report from ..util import * from ..xml import * -from .. import util +from .. import util, config from .material import * from .skeleton import Skeleton diff --git a/io_ogre/ogre/node_anim.py b/io_ogre/ogre/node_anim.py index bb08d47..9a906a7 100644 --- a/io_ogre/ogre/node_anim.py +++ b/io_ogre/ogre/node_anim.py @@ -1,19 +1,3 @@ - -# When bpy is already in local, we know this is not the initial import... -if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib - import importlib - if "config" in locals(): - importlib.reload(config) - if "report" in locals(): - importlib.reload(report) - if "xml" in locals(): - importlib.reload(xml) - if "util" in locals(): - importlib.reload(util) - -# This is only relevant on first run, on later reloads those modules -# are already in locals() and those statements do not do anything. import bpy, mathutils, logging, time from .. import config from ..report import Report diff --git a/io_ogre/ogre/ogre_import.py b/io_ogre/ogre/ogre_import.py index b989512..fe019ca 100644 --- a/io_ogre/ogre/ogre_import.py +++ b/io_ogre/ogre/ogre_import.py @@ -105,13 +105,11 @@ """ # When bpy is already in local, we know this is not the initial import... -if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib - import importlib - if "material_parser" in locals(): - importlib.reload(material_parser.MaterialParser) +#if "bpy" in locals(): +# import importlib +# print("RELOADING: material_parser.MaterialParser") +# importlib.reload(material_parser) -#from Blender import * import bpy from xml.dom import minidom from mathutils import Vector, Matrix diff --git a/io_ogre/ogre/program.py b/io_ogre/ogre/program.py index 8e4b7d2..90bf747 100644 --- a/io_ogre/ogre/program.py +++ b/io_ogre/ogre/program.py @@ -1,13 +1,3 @@ - -# When bpy is already in local, we know this is not the initial import... -if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib - import importlib - if "config" in locals(): - importlib.reload(config) - -# This is only relevant on first run, on later reloads those modules -# are already in locals() and those statements do not do anything. import os, logging from .. import config diff --git a/io_ogre/ogre/scene.py b/io_ogre/ogre/scene.py index 5c4dd07..c536f84 100644 --- a/io_ogre/ogre/scene.py +++ b/io_ogre/ogre/scene.py @@ -1,39 +1,17 @@ - # When bpy is already in local, we know this is not the initial import... if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib import importlib - if "material" in locals(): - importlib.reload(material) - if "materialv2json" in locals(): - importlib.reload(materialv2json) - if "node_anim" in locals(): - importlib.reload(node_anim) - if "mesh" in locals(): - importlib.reload(mesh) - if "skeleton" in locals(): - importlib.reload(skeleton) - if "config" in locals(): - importlib.reload(config) - if "util" in locals(): - importlib.reload(util) - if "report" in locals(): - importlib.reload(report) - if "xml" in locals(): - importlib.reload(xml) - -# This is only relevant on first run, on later reloads those modules -# are already in locals() and those statements do not do anything. -import bpy, mathutils, os, getpass, math + #print("Reloading modules: material, materialv2json, node_anim, mesh, skeleton") + importlib.reload(material) + importlib.reload(materialv2json) + importlib.reload(node_anim) + importlib.reload(mesh) + importlib.reload(skeleton) + +import bpy, mathutils, os, getpass, math, logging from os.path import join -from . import material -from . import materialv2json -from . import node_anim -from . import mesh -from . import skeleton -from .. import bl_info -from .. import config -from .. import util +from . import material, materialv2json, node_anim, mesh, skeleton +from .. import bl_info, config, util from ..report import Report from ..util import * from ..xml import * diff --git a/io_ogre/ogre/skeleton.py b/io_ogre/ogre/skeleton.py index 64433e4..81cc503 100644 --- a/io_ogre/ogre/skeleton.py +++ b/io_ogre/ogre/skeleton.py @@ -1,19 +1,3 @@ - -# When bpy is already in local, we know this is not the initial import... -if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib - import importlib - if "config" in locals(): - importlib.reload(config) - if "report" in locals(): - importlib.reload(report) - if "xml" in locals(): - importlib.reload(xml) - if "util" in locals(): - importlib.reload(util) - -# This is only relevant on first run, on later reloads those modules -# are already in locals() and those statements do not do anything. import bpy, mathutils, logging, time, sys from .. import config from ..report import Report diff --git a/io_ogre/ui/__init__.py b/io_ogre/ui/__init__.py index 95cf83c..ded9100 100644 --- a/io_ogre/ui/__init__.py +++ b/io_ogre/ui/__init__.py @@ -1,29 +1,17 @@ -import bpy - # When bpy is already in local, we know this is not the initial import... if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib import importlib - if "config" in locals(): - importlib.reload(config) - if "report" in locals(): - importlib.reload(report) - if "importer" in locals(): - importlib.reload(importer) - if "export" in locals(): - importlib.reload(export) - if "mesh_preview" in locals(): - importlib.reload(mesh_preview) + #print("Reloading modules: export, importer") + importlib.reload(export) + importlib.reload(importer) -# This is only relevant on first run, on later reloads those modules -# are already in locals() and those statements do not do anything. +import bpy import shutil +from os.path import exists +from . import importer, export from .. import config from ..report import Report -from . import importer -from . import export from ..mesh_preview import OGREMESH_OT_preview -from os.path import exists # Variable to visibility state of the mesh preview button is displayed meshpreviewButtonDisplayed = False diff --git a/io_ogre/ui/export.py b/io_ogre/ui/export.py index eefed8e..ddc01a9 100644 --- a/io_ogre/ui/export.py +++ b/io_ogre/ui/export.py @@ -1,35 +1,21 @@ +## When bpy is already in local, we know this is not the initial import... +if "bpy" in locals(): + import importlib + #print("Reloading modules: scene") + importlib.reload(material) + importlib.reload(mesh) + importlib.reload(scene) + importlib.reload(skeleton) + import bpy, os, getpass, math, mathutils, logging from pprint import pprint - -# When bpy is already in local, we know this is not the initial import... -if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib - import importlib - if "config" in locals(): - importlib.reload(config) - if "mesh" in locals(): - importlib.reload(mesh) - if "skeleton" in locals(): - importlib.reload(skeleton) - if "scene" in locals(): - importlib.reload(scene) - if "material" in locals(): - importlib.reload(material) - if "report" in locals(): - importlib.reload(report) - -# This is only relevant on first run, on later reloads those modules -# are already in locals() and those statements do not do anything. from bpy.props import EnumProperty, BoolProperty, FloatProperty, StringProperty, IntProperty from .. import config -from ..ogre import material -from ..ogre import mesh -from ..ogre import scene -from ..ogre import skeleton from ..report import Report from ..util import * from ..xml import * +from ..ogre import material, mesh, scene, skeleton logger = logging.getLogger('export') @@ -60,9 +46,10 @@ def __init__(self): def invoke(self, context, event): # Update the interface with the config values for key, value in config.CONFIG.items(): - if getattr(self, "EX_" + key, None) or getattr(self, "EX_Vx_" + key, None) or getattr(self, "EX_V1_" + key, None) or getattr(self, "EX_V2_" + key, None): - # todo: isn't the key missing the "EX_" prefix? - setattr(self,key,value) + for prefix in ["EX_", "EX_Vx_", "EX_V1_", "EX_V2_"]: + attr_name = prefix + key + if getattr(self, attr_name, None) is not None: + setattr(self, attr_name, value) if not self.filepath: blend_filepath = context.blend_data.filepath @@ -146,7 +133,6 @@ def execute(self, context): # Update saved defaults to new settings and also print export code kw = {} - conf_name = "" print ("_" * 80,"\n") @@ -155,15 +141,21 @@ def execute(self, context): print("bpy.ops.ogre.export(") print(" filepath='%s', " % os.path.abspath(self.filepath).replace('\\', '\\\\')) for name in dir(_OgreCommonExport_): - if name.startswith('EX_V1_') or name.startswith('EX_V2_') or name.startswith('EX_Vx_'): + conf_name = "" + if name.startswith('EX_V1_') or \ + name.startswith('EX_V2_') or \ + name.startswith('EX_Vx_'): conf_name = name[6:] elif name.startswith('EX_'): conf_name = name[3:] - kw[ conf_name ] = getattr(self, name) - if name.startswith('EX_') and config._CONFIG_DEFAULTS_ALL[ conf_name ] != getattr(self, name): - print(" %s=%s, " % (name, getattr(self, name))) - config.update(**kw) + if conf_name not in config.CONFIG.keys(): + continue + attribute = getattr(self, name) + kw[ conf_name ] = attribute + if config._CONFIG_DEFAULTS_ALL[ conf_name ] != attribute: + print(" %s=%s, " % (name, attribute)) print(")") + config.update(**kw) print ("_" * 80,"\n") @@ -436,19 +428,19 @@ def execute(self, context): name="Shape Normals", description="Export normals in shape animations (updates the .mesh file)", default=config.get('SHAPE_NORMALS')) = {} - + # Logging EX_Vx_ENABLE_LOGGING : BoolProperty( name="Write Exporter Logs", description="Write Log file to the output directory (blender2ogre.log)", default=config.get('ENABLE_LOGGING')) = {} - + # It seems that it is not possible to exclude DEBUG when selecting a log level EX_Vx_DEBUG_LOGGING : BoolProperty( name="Debug Logging", description="Whether to show DEBUG log messages", default=config.get('DEBUG_LOGGING')) = {} - + # It was decided to make this an option that is not user-facing #EX_Vx_SHOW_LOG_NAME : BoolProperty( # name="Show Log name", diff --git a/io_ogre/ui/importer.py b/io_ogre/ui/importer.py index 84c6a27..70aa1e4 100644 --- a/io_ogre/ui/importer.py +++ b/io_ogre/ui/importer.py @@ -1,26 +1,18 @@ -import bpy, os, getpass, math, mathutils, logging - -from pprint import pprint - # When bpy is already in local, we know this is not the initial import... if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib import importlib - if "config" in locals(): - importlib.reload(config) - if "ogre_import" in locals(): - importlib.reload(ogre_import) - if "util" in locals(): - importlib.reload(util) - -# This is only relevant on first run, on later reloads those modules -# are already in locals() and those statements do not do anything. + #print("Reloading modules: ogre_import") + importlib.reload(ogre_import) + +import bpy, os, getpass, math, mathutils, logging + +from pprint import pprint from bpy.props import EnumProperty, BoolProperty, FloatProperty, StringProperty, IntProperty from .. import config -from ..ogre import ogre_import from ..report import Report from ..util import * from ..xml import * +from ..ogre import ogre_import logger = logging.getLogger('import') @@ -53,9 +45,10 @@ def __init__(self): def invoke(self, context, event): # Update the interface with the config values for key, value in config.CONFIG.items(): - if getattr(self, "IM_" + key, None) or getattr(self, "IM_Vx_" + key, None) or getattr(self, "IM_V1_" + key, None) or getattr(self, "IM_V2_" + key, None): - # todo: isn't the key missing the "IM_" prefix? - setattr(self,key,value) + for prefix in ["IM_", "IM_Vx_", "IM_V1_", "IM_V2_"]: + attr_name = prefix + key + if getattr(self, attr_name, None) is not None: + setattr(self, attr_name, value) wm = context.window_manager fs = wm.fileselect_add(self) @@ -139,7 +132,6 @@ def execute(self, context): # Update saved defaults to new settings and also print import code kw = {} - conf_name = "" print ("_" * 80,"\n") @@ -148,15 +140,21 @@ def execute(self, context): print("bpy.ops.ogre.import_mesh(") print(" filepath='%s', " % os.path.abspath(self.filepath).replace('\\', '\\\\')) for name in dir(_OgreCommonImport_): - if name.startswith('IM_V1_') or name.startswith('IM_V2_') or name.startswith('IM_Vx_'): + conf_name = "" + if name.startswith('IM_V1_') or \ + name.startswith('IM_V2_') or \ + name.startswith('IM_Vx_'): conf_name = name[6:] elif name.startswith('IM_'): conf_name = name[3:] - kw[ conf_name ] = getattr(self, name) - if name.startswith('IM_') and config._CONFIG_DEFAULTS_ALL[ conf_name ] != getattr(self, name): - print(" %s=%s, " % (name, getattr(self, name))) - config.update(**kw) + if conf_name not in config.CONFIG.keys(): + continue + attribute = getattr(self, name) + kw[ conf_name ] = attribute + if config._CONFIG_DEFAULTS_ALL[ conf_name ] != attribute: + print(" %s=%s, " % (name, attribute)) print(")") + config.update(**kw) print ("_" * 80,"\n") @@ -273,7 +271,7 @@ def execute(self, context): name="Import shape keys", description="Import shape keys (morphs)", default=config.get('IMPORT_SHAPEKEYS')) = {} - + # Logging IM_Vx_ENABLE_LOGGING : BoolProperty( name="Write Importer Logs", diff --git a/io_ogre/util.py b/io_ogre/util.py index d25cbed..5cb6821 100644 --- a/io_ogre/util.py +++ b/io_ogre/util.py @@ -1,17 +1,7 @@ - -# When bpy is already in local, we know this is not the initial import... -if "bpy" in locals(): - # ...so we need to reload our submodule(s) using importlib - import importlib - if "config" in locals(): - importlib.reload(config) - -# This is only relevant on first run, on later reloads those modules -# are already in locals() and those statements do not do anything. -from . import config -from . report import Report from os.path import split, splitext import bpy, logging, logging, mathutils, os, re, subprocess, sys, time +from . import config +from . report import Report logger = logging.getLogger('util')