diff --git a/.flake8 b/.flake8
deleted file mode 100644
index a390455..0000000
--- a/.flake8
+++ /dev/null
@@ -1,10 +0,0 @@
-[flake8]
-max-line-length = 120
-ignore = E203, E501, W503, F722, F821 # Incompatible with black, F722, F821 because of bug in Flake with names and strings
-
-exclude =
- .git
- .history
- .venv
- .vscode
- __pycache__
diff --git a/.gitignore b/.gitignore
index 74ac996..6bb9bd6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,7 @@ _PackagesForInstall
.venv
# VS Code
-.vscode
+# .vscode
.vscode/settings.json
.local
diff --git a/.vscode/settings.json b/.vscode/settings.json
index de153a1..04cb4ff 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -16,7 +16,11 @@
"python.testing.unittestEnabled": false,
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true,
- "python.linting.flake8Args": [],
+ "python.linting.flake8Args": [
+ "--max-line-length=120",
+ "--ignore=E402,E203,E501,W503,F722,F821",
+ "--exclude=.git,.history,.venv,.vscode,__pycache__"
+ ],
"python.linting.enabled": true,
"gitlab.instanceUrl": "https://gitlab-ncsa.ubisoft.org/",
"blender.addon.sourceDirectory": "./stampinfo",
@@ -25,11 +29,15 @@
"python.testing.nosetestsEnabled": false,
"restructuredtext.confPath": "${workspaceFolder}\\docs",
"spellright.language": [
- "en"
+ "en",
+ "fr"
],
"spellright.documentTypes": [
"markdown",
"latex",
"plaintext"
- ]
+ ],
+ "blender.addon.sourceDirectory": "./stampinfo",
+ "restructuredtext.confPath": "${workspaceFolder}\\docs",
+ "esbonio.sphinx.confDir": ""
}
\ No newline at end of file
diff --git a/.vscode/settings.shared.json b/.vscode/settings.shared.json
new file mode 100644
index 0000000..1568d91
--- /dev/null
+++ b/.vscode/settings.shared.json
@@ -0,0 +1,42 @@
+{
+ "editor.formatOnSave": true,
+ "python.pythonPath": ".venv\\Scripts\\python.exe",
+ "python.formatting.provider": "black",
+ "python.formatting.blackArgs": [
+ "--line-length",
+ "120"
+ ],
+ "python.testing.unittestArgs": [
+ "-v",
+ "-s",
+ "./tests",
+ "-p",
+ "test_*.py"
+ ],
+ "python.testing.unittestEnabled": false,
+ "python.linting.pylintEnabled": false,
+ "python.linting.flake8Enabled": true,
+ "python.linting.flake8Args": [
+ "--max-line-length=120",
+ "--ignore=E402,E203,E501,W503,F722,F821",
+ "--exclude=.git,.history,.venv,.vscode,__pycache__"
+ ],
+ "python.linting.enabled": true,
+ "gitlab.instanceUrl": "https://gitlab-ncsa.ubisoft.org/",
+ "blender.addon.sourceDirectory": "./stampinfo",
+ "python.testing.promptToConfigure": false,
+ "python.testing.pytestEnabled": false,
+ "python.testing.nosetestsEnabled": false,
+ "restructuredtext.confPath": "${workspaceFolder}\\docs",
+ "spellright.language": [
+ "en",
+ "fr"
+ ],
+ "spellright.documentTypes": [
+ "markdown",
+ "latex",
+ "plaintext"
+ ],
+ "blender.addon.sourceDirectory": "./stampinfo",
+ "restructuredtext.confPath": "${workspaceFolder}\\docs"
+}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 649f7f4..bb2c533 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,15 @@
+# 1.1.1 (2022-05-11)
+
+## Code
+
+- Code cleaning and updated to match the implementation of Ubisoft Shot Manager add-on
+- Added custom class of Logger
+- changed the global debug variable gbWkDebug to a variable devDebug stored in config.py
# 1.0.17 (2022-01-15)
-evaluateRenderResolutionForStampInfo
+
+- Added function evaluateRenderResolutionForStampInfo
+
# 1.0.15 (2021-11-02)
@@ -10,7 +19,6 @@ evaluateRenderResolutionForStampInfo
- Added a text field for Sequence
- Set date and time on by default
-
# 1.0.14 (2021-10-29)
@@ -19,8 +27,6 @@ evaluateRenderResolutionForStampInfo
- Logos built-in path was broken
-
-
# 1.0.13 (2021-09-28)
## Installation
@@ -28,8 +34,6 @@ evaluateRenderResolutionForStampInfo
- Improved again error catching for better user feedback when not in admin mode
-
-
# 1.0.12 (2021-09-23)
## Installation
@@ -37,8 +41,6 @@ evaluateRenderResolutionForStampInfo
- Improved error catching with pip download timeout
-
-
# 1.0.11 (2021-09-23)
## Documentation
@@ -50,8 +52,6 @@ evaluateRenderResolutionForStampInfo
- Provided better user feedback at install time in case of errors
-
-
# 1.0.9 (2021-08-20)
## UI
@@ -63,16 +63,12 @@ evaluateRenderResolutionForStampInfo
- Fix: Frame ranges are now disabled again when unchecked in the UI
-
-
# 1.0.8 (05/07/2021)
- Rewamped UI
- Improved documentation
-
-
# 1.0.1 (2021-06-12)
- Removed handlers and use of the compositing editor that were used to generate the final images
@@ -80,8 +76,6 @@ because code was unstable and complicated
- Added 2 Render buttons and a batch based on the VSE to create the final images
-
-
--------
# 0.9.x - Production versions
diff --git a/requirements-dev.txt b/requirements-dev.txt
index c53d2f6..1eb6c7d 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,18 +1,45 @@
+alabaster==0.7.12
appdirs==1.4.4
-attrs==19.3.0
-black==19.10b0
-click==7.1.2
+attrs==21.4.0
+Babel==2.10.1
+black==22.3.0
+certifi==2021.10.8
+charset-normalizer==2.0.12
+click==8.1.3
+colorama==0.4.4
+docutils==0.17.1
fake-bpy-module-2.82==20200514
-flake8==3.8.1
-flake8-black==0.1.2
-flake8-bugbear==20.1.4
-importlib-metadata==1.6.0
+flake8==4.0.1
+flake8-black==0.3.2
+flake8-bugbear==22.4.25
+idna==3.3
+imagesize==1.3.0
+importlib-metadata==4.11.3
+Jinja2==3.1.2
+MarkupSafe==2.1.1
mccabe==0.6.1
-pathspec==0.8.0
-pycodestyle==2.6.0
-pyflakes==2.2.0
-regex==2020.5.14
-toml==0.10.1
-typed-ast==1.4.1
-typing==3.7.4.1
-zipp==3.1.0
+mypy-extensions==0.4.3
+packaging==21.3
+pathspec==0.9.0
+platformdirs==2.5.2
+pycodestyle==2.8.0
+pyflakes==2.4.0
+Pygments==2.12.0
+pyparsing==3.0.9
+pytz==2022.1
+regex==2022.4.24
+requests==2.27.1
+snowballstemmer==2.2.0
+Sphinx==4.5.0
+sphinxcontrib-applehelp==1.0.2
+sphinxcontrib-devhelp==1.0.2
+sphinxcontrib-htmlhelp==2.0.0
+sphinxcontrib-jsmath==1.0.1
+sphinxcontrib-qthelp==1.0.3
+sphinxcontrib-serializinghtml==1.1.5
+toml==0.10.2
+tomli==2.0.1
+typed-ast==1.5.3
+typing==3.7.4.3
+urllib3==1.26.9
+zipp==3.8.0
diff --git a/stampinfo/__init__.py b/stampinfo/__init__.py
index ae94c56..0fdcfcf 100644
--- a/stampinfo/__init__.py
+++ b/stampinfo/__init__.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -18,14 +18,13 @@
"""
Main init
"""
-import logging
-import os
-from pathlib import Path
+# import os
+# from pathlib import Path
import bpy
import bpy.utils.previews
-from bpy.props import PointerProperty
+from bpy.props import IntProperty, PointerProperty
from .config import config
@@ -43,14 +42,18 @@
importlib.reload(stamper)
importlib.reload(debug)
+from stampinfo.config import sm_logging
+
+_logger = sm_logging.getLogger(__name__)
+
bl_info = {
"name": "Stamp Info",
"author": "Julien Blervaque (aka Werwack) - Ubisoft",
"description": "Stamp scene information on the rendered images",
- "blender": (3, 0, 0),
- "version": (1, 0, 17),
- "location": "Right panel in the 3D View",
+ "blender": (3, 1, 0),
+ "version": (1, 1, 1),
+ "location": "View3D > Stamp Info",
"wiki_url": "https://ubisoft-stampinfo.readthedocs.io",
"tracker_url": "https://github.com/ubisoft/stampinfo/issues",
"support": "COMMUNITY",
@@ -65,36 +68,38 @@
# Logging
###########
-_logger = logging.getLogger(__name__)
-_logger.propagate = False
-MODULE_PATH = Path(__file__).parent.parent
-logging.basicConfig(level=logging.INFO)
-_logger.setLevel(logging.DEBUG) # CRITICAL ERROR WARNING INFO DEBUG NOTSET
+# _logger = sm_logging.getLogger(__name__)
+# _logger.propagate = False
+# MODULE_PATH = Path(__file__).parent.parent
+# logging.basicConfig(level=logging.INFO)
+# _logger.setLevel(logging.DEBUG) # CRITICAL ERROR WARNING INFO DEBUG NOTSET
+
+import logging
pil_logger = logging.getLogger("PIL")
pil_logger.setLevel(logging.INFO)
-# _logger.info(f"Logger {}")
-# _logger.warning(f"logger {}")
-# _logger.error(f"error {}")
-# _logger.debug(f"debug {}")
+# # _logger.info(f"Logger {}")
+# # _logger.warning(f"logger {}")
+# # _logger.error(f"error {}")
+# # _logger.debug(f"debug {}")
-class Formatter(logging.Formatter):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
+# class Formatter(logging.Formatter):
+# def __init__(self, *args, **kwargs):
+# super().__init__(*args, **kwargs)
- def format(self, record: logging.LogRecord):
- """
- The role of this custom formatter is:
- - append filepath and lineno to logging format but shorten path to files, to make logs more clear
- - to append "./" at the begining to permit going to the line quickly with VS Code CTRL+click from terminal
- """
- s = super().format(record)
- # s = record
- pathname = Path(record.pathname).relative_to(MODULE_PATH)
- s += f" [{os.curdir}{os.sep}{pathname}:{record.lineno}]"
- return s
+# def format(self, record: logging.LogRecord):
+# """
+# The role of this custom formatter is:
+# - append filepath and lineno to logging format but shorten path to files, to make logs more clear
+# - to append "./" at the begining to permit going to the line quickly with VS Code CTRL+click from terminal
+# """
+# s = super().format(record)
+# # s = record
+# pathname = Path(record.pathname).relative_to(MODULE_PATH)
+# s += f" [{os.curdir}{os.sep}{pathname}:{record.lineno}]"
+# return s
classes = (
@@ -114,20 +119,29 @@ def stampInfo_resetProperties():
def register():
+
+ config.initGlobalVariables()
+
from .utils import utils_ui
utils_ui.register()
utils.display_addon_registered_version("Stamp Info")
- config.initGlobalVariables()
- # logging
- ###################
- if len(_logger.handlers) == 0:
- _logger.setLevel(logging.WARNING)
- formatter = Formatter("{asctime} {levelname[0]} {name:<36} - {message:<80}", style="{")
- handler = logging.StreamHandler()
- handler.setFormatter(formatter)
- _logger.addHandler(handler)
+ sm_logging.initialize()
+ if config.devDebug:
+ _logger.setLevel("DEBUG") # CRITICAL ERROR WARNING INFO DEBUG NOTSET
+
+ logger_level = f"Logger level: {sm_logging.getLevelName()}"
+ versionTupple = utils.display_addon_registered_version("Stamp Info", more_info=logger_level)
+
+ # # logging
+ # ###################
+ # if len(_logger.handlers) == 0:
+ # _logger.setLevel(logging.WARNING)
+ # formatter = Formatter("{asctime} {levelname[0]} {name:<36} - {message:<80}", style="{")
+ # handler = logging.StreamHandler()
+ # handler.setFormatter(formatter)
+ # _logger.addHandler(handler)
# install dependencies and required Python libraries
###################
@@ -149,6 +163,14 @@ def register():
from .addon_prefs import addon_prefs
from .operators import render_operators
+ ###################
+ # update data
+ ###################
+
+ bpy.types.WindowManager.UAS_stamp_info_version = IntProperty(
+ name="Add-on Version Int", description="Add-on version as integer", default=versionTupple[1]
+ )
+
for cls in classes:
bpy.utils.register_class(cls)
@@ -201,6 +223,8 @@ def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
+ del bpy.types.WindowManager.UAS_stamp_info_version
+
utils_ui.unregister()
config.releaseGlobalVariables()
diff --git a/stampinfo/addon_prefs/addon_prefs.py b/stampinfo/addon_prefs/addon_prefs.py
index 18c1d62..3888bb8 100644
--- a/stampinfo/addon_prefs/addon_prefs.py
+++ b/stampinfo/addon_prefs/addon_prefs.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,24 +21,55 @@
import bpy
from bpy.types import AddonPreferences
-from bpy.props import BoolProperty
+from bpy.props import IntProperty, BoolProperty
+
+from .addon_prefs_ui import draw_addon_prefs
+
+from stampinfo.utils import utils
from ..config import config
from ..ui.dependencies_ui import drawDependencies
+from stampinfo.config import sm_logging
+
+_logger = sm_logging.getLogger(__name__)
+
class UAS_StampInfo_AddonPrefs(AddonPreferences):
"""
- Use this to get these prefs:
- prefs = context.preferences.addons["stampinfo"].preferences
+ Use this to get these prefs:
+ prefs = context.preferences.addons["stampinfo"].preferences
"""
# this must match the add-on name, use '__package__'
# when defining this in a submodule of a python package
bl_idname = "stampinfo"
+ def version(self):
+ """Return the add-on version in the form of a tupple made by:
+ - a string x.y.z (eg: "1.21.3")
+ - an integer. x.y.z becomes xxyyyzzz (eg: "1.21.3" becomes 1021003)
+ Return None if the addon has not been found
+ """
+ return utils.addonVersion("Stamp Info")
+
+ newAvailableVersion: IntProperty(
+ description="Store the version of the latest release of the add-on as an integer if there is an online release"
+ "\nthat is more recent than this version. If there is none then the value is 0",
+ # default=2005001,
+ default=1007016,
+ )
+
+ isInitialized: BoolProperty(
+ default=False,
+ )
+
+ def initialize_stamp_info_prefs(self):
+ print("\nInitializing Stamp Info Preferences...")
+
install_failed: BoolProperty(
- name="Install failed", default=False,
+ name="Install failed",
+ default=False,
)
mediaFirstFrameIsZero: BoolProperty(
@@ -72,62 +103,18 @@ class UAS_StampInfo_AddonPrefs(AddonPreferences):
options=set(),
)
+ ##################################################################################
+ # Draw
+ ##################################################################################
def draw(self, context):
- layout = self.layout
- splitFactor = 0.3
-
- box = layout.box()
- row = box.row()
- row.separator(factor=3)
- subCol = row.column()
- subCol.prop(self, "mediaFirstFrameIsZero")
- subCol.prop(self, "write_still")
-
- layout.separator(factor=0.5)
- layout.label(text="Technical Settings:")
- box = layout.box()
- box.label(text="Stamped Images Compositing:")
- row = box.row()
- row.separator(factor=3)
- subCol = row.column()
- subCol.prop(self, "delete_temp_scene")
- subCol.prop(self, "delete_temp_images")
-
- # Dependencies
- ###############
- drawDependencies(context, layout)
-
- # Dev and debug
- ###############
- box = layout.box()
-
- split = box.split(factor=splitFactor)
- rowLeft = split.row()
- rowLeft.label(text="Development and Debug:")
- rowRight = split.row()
-
- if config.devDebug:
- strDebug = " *** Debug Mode is On ***"
- rowRight.alignment = "RIGHT"
- rowRight.alert = True
- rowRight.label(text=strDebug)
-
- split = box.split(factor=splitFactor)
- rowLeft = split.row()
- rowLeft.alignment = "RIGHT"
- rowLeft.label(text="Debug Mode")
- rowRight = split.row()
- if config.devDebug:
- rowRight.alert = True
- rowRight.operator("uas_stamp_info.enable_debug", text="Turn Off").enable_debug = False
- else:
- rowRight.operator("uas_stamp_info.enable_debug", text="Turn On").enable_debug = True
+ draw_addon_prefs(self, context)
# -----------------------------------------------------------
# UI user preferences - Not exposed
# -----------------------------------------------------------
panelExpanded_mode: BoolProperty(
- name="Expand Render Mode Properties", default=True,
+ name="Expand Render Mode Properties",
+ default=True,
)
@@ -135,11 +122,14 @@ def draw(self, context):
def register():
+ _logger.debug_ext(" - Registering Add-on Prefs Package", form="REG")
+
for cls in _classes:
bpy.utils.register_class(cls)
def unregister():
+ _logger.debug_ext(" - Unregistering Add-on Prefs Package", form="UNREG")
+
for cls in reversed(_classes):
bpy.utils.unregister_class(cls)
-
diff --git a/stampinfo/addon_prefs/addon_prefs_ui.py b/stampinfo/addon_prefs/addon_prefs_ui.py
new file mode 100644
index 0000000..83cf72e
--- /dev/null
+++ b/stampinfo/addon_prefs/addon_prefs_ui.py
@@ -0,0 +1,82 @@
+# GPLv3 License
+#
+# Copyright (C) 2021 Ubisoft
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""
+UI for the Add-on Preferences
+"""
+
+from stampinfo.config import config
+from stampinfo.ui.dependencies_ui import drawDependencies
+from stampinfo.utils.utils_ui import collapsable_panel
+
+##################################################################################
+# Draw
+##################################################################################
+
+
+def draw_addon_prefs(self, context):
+ layout = self.layout
+ # layout = layout.column(align=False)
+
+ splitFactor = 0.3
+
+ box = layout.box()
+ row = box.row()
+ row.separator(factor=3)
+ subCol = row.column()
+ subCol.prop(self, "mediaFirstFrameIsZero")
+ subCol.prop(self, "write_still")
+
+ layout.separator(factor=0.5)
+ layout.label(text="Technical Settings:")
+ box = layout.box()
+ box.label(text="Stamped Images Compositing:")
+ row = box.row()
+ row.separator(factor=3)
+ subCol = row.column()
+ subCol.prop(self, "delete_temp_scene")
+ subCol.prop(self, "delete_temp_images")
+
+ # Dependencies
+ ###############
+ drawDependencies(context, layout)
+
+ # Dev and debug
+ ###############
+ box = layout.box()
+
+ split = box.split(factor=splitFactor)
+ rowLeft = split.row()
+ rowLeft.label(text="Development and Debug:")
+ rowRight = split.row()
+
+ if config.devDebug:
+ strDebug = " *** Debug Mode is On ***"
+ rowRight.alignment = "RIGHT"
+ rowRight.alert = True
+ rowRight.label(text=strDebug)
+
+ split = box.split(factor=splitFactor)
+ rowLeft = split.row()
+ rowLeft.alignment = "RIGHT"
+ rowLeft.label(text="Debug Mode")
+ rowRight = split.row()
+ if config.devDebug:
+ rowRight.alert = True
+ rowRight.operator("uas_stamp_info.enable_debug", text="Turn Off").enable_debug = False
+ else:
+ rowRight.operator("uas_stamp_info.enable_debug", text="Turn On").enable_debug = True
diff --git a/stampinfo/config/config.py b/stampinfo/config/config.py
index d8f2754..e64c3f8 100644
--- a/stampinfo/config/config.py
+++ b/stampinfo/config/config.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -33,8 +33,8 @@ def initGlobalVariables():
else:
devDebug = False
- # force debug mode
- # devDebug = False
+ # change this value to force debug at start time
+ devDebug = True
global devDebug_keepVSEContent
devDebug_keepVSEContent = True and devDebug
@@ -42,7 +42,19 @@ def initGlobalVariables():
if devDebug:
print("Dev debug: ", devDebug)
+ global devDebug_ignoreLoggerFormatting
+ devDebug_ignoreLoggerFormatting = True and devDebug
+
def releaseGlobalVariables():
pass
+
+
+def getLoggingTags():
+ tags = dict()
+
+ # debug tags
+ tags["DEPRECATED"] = False
+
+ return tags
diff --git a/stampinfo/config/sm_logging.py b/stampinfo/config/sm_logging.py
new file mode 100644
index 0000000..29d4f8e
--- /dev/null
+++ b/stampinfo/config/sm_logging.py
@@ -0,0 +1,328 @@
+# GPLv3 License
+#
+# Copyright (C) 2022 Ubisoft
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""
+Logging for Stamp Info
+
+Read this: https://stackoverflow.com/questions/7274732/extending-the-python-logger
+
+"""
+
+import os
+from pathlib import Path
+
+import logging
+
+# from logging import DEBUG, INFO, ERROR
+
+from ..utils.utils_python import asciiColor
+from ..config import config
+
+
+def getLogger(name):
+ return _logger
+
+
+def getLevelName():
+ return logging.getLevelName(_logger.level)
+
+
+# cf https://stackoverflow.com/questions/7274732/extending-the-python-logger
+
+
+class SM_Logger(logging.getLoggerClass()):
+ def __init__(self, name):
+ super(SM_Logger, self).__init__(name)
+
+ self._prefix = "StampInfo"
+ self._defaultColor = "WHITE"
+ self._defaultForm = "STD"
+
+ # colors in terminal: https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output
+ # Eg:
+ # _YELLOW = '\33[33m'
+ # _ENDCOLOR = '\033[0m'
+ # print(f"{_YELLOW}text{_ENDCOLOR}")
+
+ # 1; :bold
+ self._colors = {
+ "BLUE": "\33[34m",
+ "BLUE_LIGHT": "\33[1;34m",
+ "GREEN": "\33[32m",
+ "GREEN_LIGHT": "\33[1;32m",
+ "GRAY": "\33[1;30m",
+ "YELLOW": "\33[33m",
+ "YELLOW_LIGHT": "\33[1;33m",
+ "ORANGE": asciiColor(255, 165, 0),
+ "RED": "\33[31m",
+ "RED_BG": "\33[41m",
+ "PINK": asciiColor(255, 192, 203),
+ "PURPLE": "\33[35m",
+ "PURPULE_LIGHT": "\33[1;35m",
+ "TURQUOISE": "\33[36m",
+ "TURQUOISE_LIGHT": "\33[1;36m",
+ "WHITE": "\33[37m",
+ }
+
+ # self._formatter_standard = Formatter("\33[36m" + "~Basic +++" + " {message:<140}" + "\033[0m", style="{")
+ self._formatter_standard = Formatter(self._prefix + " - " + " {message:<110}", style="{")
+ self._formatter_basic = Formatter("\33[36m" + "~Basic +++" + " {message:<140}" + "\033[0m", style="{")
+ self._formatter_other = Formatter("\33[36m" + "S OTHER M+" + " {message:<140}" + "\033[0m", style="{")
+ self._formatter = {
+ "STD": self._formatter_standard,
+ "BASIC": self._formatter_basic,
+ "OTHER": self._formatter_other,
+ }
+
+ self.tags = config.getLoggingTags()
+
+ @property
+ def prefix(self):
+ return self._prefix
+
+ @prefix.setter
+ def prefix(self, value):
+ self._prefix = value
+
+ def _getFormatter(self, col="", form="DEFAULT"):
+ color = self._colors[col] if col != "" else ""
+ _ENDCOLOR = "\033[0m"
+
+ if "STD" == form:
+ f = Formatter(color + self._prefix + " {message:<120}" + _ENDCOLOR, style="{")
+ elif "REG" == form:
+ if "" == col:
+ color = self._colors["YELLOW"]
+ f = Formatter(color + "{message:<90}" + _ENDCOLOR, style="{")
+ elif "UNREG" == form:
+ if "" == col:
+ color = self._colors["GRAY"]
+ f = Formatter(color + "{message:<90}" + _ENDCOLOR, style="{")
+ elif "DEPRECATED" == form:
+ if "" == col:
+ color = self._colors["ORANGE"]
+ f = Formatter(color + "[DEPRECATED] {message:<90}" + _ENDCOLOR, style="{")
+ elif "WARNING" == form:
+ if "" == col:
+ color = self._colors["ORANGE"]
+ f = Formatter(color + self.prefix + " *** Warning" + " {message:<140}" + _ENDCOLOR, style="{")
+ elif "ERROR" == form:
+ if "" == col:
+ color = self._colors["RED"]
+ f = Formatter(color + "Stamp Info: " + " {message:<140}" + _ENDCOLOR, style="{")
+ elif "CRITICAL" == form:
+ if "" == col:
+ color = self._colors["RED_BG"]
+ f = Formatter(color + "Stamp Info: " + " {message:<140}" + _ENDCOLOR, style="{")
+ elif "OTHER" == form:
+ f = Formatter(color + "~Other +++" + " {message:<140}" + _ENDCOLOR, style="{")
+ else: # "DEFAULT"
+ f = Formatter("\033[0m" + "~default +++" + " {message:<140}", style="{")
+ return f
+
+ # def debug_basic(self, msg, extra=None, color="GREEN", formatter="OTHER"):
+ # ch = logging.StreamHandler()
+ # ch.setLevel(logging.DEBUG)
+ # ### ch.setFormatter(self.formatter_basic)
+ # # _logger.handlers[0].setFormatter(self.formatter_basic)
+ # _logger.handlers[0].setFormatter(self._formatter[formatter])
+ # super(SM_Logger, self).debug((self._colors[color] + "{}\033[0m").format(msg), extra=extra)
+ # # ch.setFormatter(self.formatter_other)
+ # _logger.handlers[0].setFormatter(self._formatter["OTHER"])
+
+ def debug_form(self, col="GREEN", form="DEFAULT"):
+ """Set formatter. To use before call to debug()
+ eg: _logger.debug_form(col="GREEN", form="STD")
+ _logger.debug("debug test timer green")
+ """
+ ch = logging.StreamHandler()
+ ch.setLevel(logging.DEBUG)
+ _logger.handlers[0].setFormatter(self._getFormatter(col, form))
+
+ def _print_ext(self, mode, msg, extra=None, col="", form="STD", tag=None, display=True):
+ """
+ Args:
+ mode: "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"
+ """
+ if not display:
+ return
+
+ # accept or silence message display according to tags (if return is enabled then tag is ignored)
+ if tag is not None:
+ if tag in self.tags:
+ if not self.tags[tag]:
+ return
+
+ if "DEPRECATED" == tag:
+ form = "DEPRECATED"
+
+ _logger.handlers[0].setFormatter(self._getFormatter(col, form))
+
+ # Note: marvellous parameter: stacklevel allows to get the call from the sender, otherwise
+ # it is this function that is used and the path is not good
+ # cf https://stackoverflow.com/questions/14406347/python-logging-check-location-of-log-files
+ # and https://www.py4u.net/discuss/157715
+ if "DEBUG" == mode:
+ super(SM_Logger, self).debug(("{}").format(msg), extra=extra, stacklevel=2)
+ elif "WARNING" == mode:
+ super(SM_Logger, self).warning(("{}").format(msg), extra=extra, stacklevel=2)
+ elif "ERROR" == mode:
+ super(SM_Logger, self).error(("{}").format(msg), extra=extra, stacklevel=2)
+ elif "CRITICAL" == mode:
+ super(SM_Logger, self).critical(("{}").format(msg), extra=extra, stacklevel=2)
+ # INFO
+ else:
+ super(SM_Logger, self).info(("{}").format(msg), extra=extra, stacklevel=2)
+
+ _logger.handlers[0].setFormatter(self._getFormatter(self._defaultColor, self._defaultForm))
+
+ def debug_ext(self, msg, extra=None, col="", form="STD", tag=None, display=True):
+ """
+ eg:
+ _logger.debug_ext(f"message: {text}", tag="DEPRECATED")
+ _logger.warning_ext(f"message: {text}")
+ """
+ self._print_ext("DEBUG", msg, extra=extra, col=col, form=form, tag=tag, display=display)
+
+ def info_ext(self, msg, extra=None, col="BLUE_LIGHT", form="STD", tag=None, display=True):
+ self._print_ext("INFO", msg, extra=extra, col=col, form=form, tag=tag, display=display)
+
+ def warning_ext(self, msg, extra=None, col="ORANGE", form="WARNING", tag=None, display=True):
+ self._print_ext("WARNING", msg, extra=extra, col=col, form=form, tag=tag, display=display)
+
+ def error_ext(self, msg, extra=None, col="RED", form="ERROR", tag=None, display=True):
+ self._print_ext("ERROR", msg, extra=extra, col=col, form=form, tag=tag, display=display)
+
+ def critical_ext(self, msg, extra=None, col="RED_BG", form="CRITICAL", tag=None, display=True):
+ self._print_ext("CRITICAL", msg, extra=extra, col=col, form=form, tag=tag, display=display)
+
+
+class Formatter(logging.Formatter):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ def format(self, record: logging.LogRecord):
+ """
+ The role of this custom formatter is:
+ - append filepath and lineno to logging format but shorten path to files, to make logs more clear
+ - to append "./" at the begining to permit going to the line quickly with VS Code Ctrl + Click from terminal
+ """
+ s = super().format(record)
+
+ MODULE_PATH = Path(__file__).parent.parent
+ # print("MODULE_PATH:" + str(MODULE_PATH))
+ pathname = Path(record.pathname).relative_to(MODULE_PATH)
+ s += f" [{os.curdir}{os.sep}{pathname}:{record.lineno}]"
+ return s
+
+
+def loggerFormatTest(message=""):
+ return
+
+ print(message)
+ # warning: put back to the application mode afterward
+ _logger.setLevel(logging.DEBUG)
+
+ _logger.debug_ext("debug message")
+ _logger.info_ext("info message")
+ _logger.warning_ext("warning message")
+ _logger.error_ext("error message")
+ _logger.critical_ext("critical message")
+
+ print("\n")
+ _logger.debug_ext("debug_ext", col="RED", form="STD")
+ _logger.debug_ext("debug_ext", col="BLUE", form="BASIC")
+
+ mes = " - Registering Test Package"
+ print(mes)
+ _logger.debug_ext(mes, form="REG")
+ _logger.debug_ext("debug test override", col="RED", form="REG")
+
+ # use normal debug() call with aformmatter set before
+ _logger.debug_form(col="GREEN", form="STD")
+ _logger.debug("debug test timer green")
+
+
+logging.setLoggerClass(SM_Logger)
+_logger = logging.getLogger(__name__)
+
+# https://docs.python.org/fr/3/howto/logging.html
+# https://stackoverflow.com/questions/11581794/how-do-i-change-the-format-of-a-python-log-message-on-a-per-logger-basis
+
+
+def initialize():
+
+ if config.devDebug:
+ # print("Initializing Logger...")
+ # print(f"len(_logger.handlers): {len(_logger.handlers)}")
+ pass
+
+ _logger.propagate = False
+
+ logging.basicConfig(level=logging.INFO)
+ _logger.setLevel(logging.INFO) # CRITICAL ERROR WARNING INFO DEBUG NOTSET
+
+ # _logger.setLevel(logging.DEBUG)
+ formatter = None
+
+ # call config.initGlobalVariables() to get the config variables (currently done in Stamp Info init)
+ if config.devDebug_ignoreLoggerFormatting:
+ ch = "~" # "\u02EB"
+ formatter = Formatter("\33[36m" + ch + " {message:<140}" + "\033[0m", style="{")
+ else:
+ # formatter = Formatter("{asctime} {levelname[0]} {name:<30} - {message:<80}", style="{")
+ formatter = Formatter(_logger.prefix + " " + " {message:<80}", style="{")
+
+ if len(_logger.handlers) == 0:
+ handler = logging.StreamHandler()
+ handler.setFormatter(formatter)
+ _logger.addHandler(handler)
+
+ else:
+ _logger.handlers[0].setFormatter(formatter)
+
+ # handler = logging.FileHandler(get_log_file())
+ # handler.setFormatter(formatter)
+ # _logger.addHandler(handler)
+
+ loggerFormatTest()
+
+
+# def get_logs_directory():
+# def _get_logs_directory():
+# import tempfile
+
+# if "MIXER_USER_LOGS_DIR" in os.environ:
+# username = os.getlogin()
+# base_shared_path = Path(os.environ["MIXER_USER_LOGS_DIR"])
+# if os.path.exists(base_shared_path):
+# return os.path.join(os.fspath(base_shared_path), username)
+# logger.error(
+# f"MIXER_USER_LOGS_DIR env var set to {base_shared_path}, but directory does not exists. Falling back to default location."
+# )
+# return os.path.join(os.fspath(tempfile.gettempdir()), "mixer")
+
+# dir = _get_logs_directory()
+# if not os.path.exists(dir):
+# os.makedirs(dir)
+# return dir
+
+
+# def get_log_file():
+# from mixer.share_data import share_data
+
+# return os.path.join(get_logs_directory(), f"mixer_logs_{share_data.run_id}.log")
diff --git a/stampinfo/icons/__init__.py b/stampinfo/icons/__init__.py
index 55e65c4..df4c3ad 100644
--- a/stampinfo/icons/__init__.py
+++ b/stampinfo/icons/__init__.py
@@ -25,8 +25,13 @@
from pathlib import Path
import bpy.utils.previews
+from stampinfo.config import sm_logging
+
+_logger = sm_logging.getLogger(__name__)
+
def register():
+ _logger.debug_ext(" - Registering Icons Package", form="REG")
global icons_col
@@ -39,6 +44,7 @@ def register():
def unregister():
+ _logger.debug_ext(" - Unregistering Icons Package", form="UNREG")
global icons_col
diff --git a/stampinfo/infoImage.py b/stampinfo/infoImage.py
index a325126..202ec2d 100644
--- a/stampinfo/infoImage.py
+++ b/stampinfo/infoImage.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -33,15 +33,15 @@
getInfoFileFullPath,
)
-import logging
+from stampinfo.config import sm_logging
-_logger = logging.getLogger(__name__)
+_logger = sm_logging.getLogger(__name__)
# Preparation of the files
def renderTmpImageWithStampedInfo(scene, currentFrame, renderPath=None, renderFilename=None, verbose=False):
- """ Called by the Pre renderer callback
- Preparation of the files
+ """Called by the Pre renderer callback
+ Preparation of the files
"""
# Notes
# - Image origine is at TOP LEFT corner
@@ -492,7 +492,10 @@ def _debug_drawPadding(borderInd):
# textProp = "Corner Note: " if stampLabel else ""
textProp = userSettings.cornerNote if stampValue else ""
img_draw.text(
- (currentTextRight - (font.getsize(textProp))[0], currentTextTop), textProp, font=font, fill=alertColorRGBA,
+ (currentTextRight - (font.getsize(textProp))[0], currentTextTop),
+ textProp,
+ font=font,
+ fill=alertColorRGBA,
)
# ---------- fps and 3D edit -------------
@@ -561,7 +564,9 @@ def _debug_drawPadding(borderInd):
# draw box
img_draw.line(
- [(colBoxLeft, currentBoxTop), (colBoxRight, currentBoxTop)], fill=textColorGray, width=boxLineThickness,
+ [(colBoxLeft, currentBoxTop), (colBoxRight, currentBoxTop)],
+ fill=textColorGray,
+ width=boxLineThickness,
)
img_draw.line(
[(colBoxLeft, currentBoxBottom), (colBoxRight, currentBoxBottom)],
@@ -569,10 +574,14 @@ def _debug_drawPadding(borderInd):
width=boxLineThickness,
)
img_draw.line(
- [(colBoxLeft, currentBoxTop), (colBoxLeft, currentBoxBottom)], fill=textColorGray, width=boxLineThickness,
+ [(colBoxLeft, currentBoxTop), (colBoxLeft, currentBoxBottom)],
+ fill=textColorGray,
+ width=boxLineThickness,
)
img_draw.line(
- [(colBoxRight, currentBoxTop), (colBoxRight, currentBoxBottom)], fill=textColorGray, width=boxLineThickness,
+ [(colBoxRight, currentBoxTop), (colBoxRight, currentBoxBottom)],
+ fill=textColorGray,
+ width=boxLineThickness,
)
# ---------------------------------
@@ -704,7 +713,10 @@ def _debug_drawPadding(borderInd):
# (currentTextRight - (font.getsize(textProp))[0], currentTextTop), textProp, font=font, fill=textColorRGBA,
# )
img_draw.text(
- (col04, currentTextTop), textProp, font=font, fill=textColorRGBA,
+ (col04, currentTextTop),
+ textProp,
+ font=font,
+ fill=textColorRGBA,
)
# ---------- file -------------
@@ -778,7 +790,7 @@ def drawRangesAndFrame(
color,
):
"""
- framemode can be '3DFRAME' or 'VIDEOFRAME'
+ framemode can be '3DFRAME' or 'VIDEOFRAME'
"""
userSettings = scene.UAS_StampInfo_Settings
diff --git a/stampinfo/install/addon_error_prefs.py b/stampinfo/install/addon_error_prefs.py
index 50e4294..1b84b16 100644
--- a/stampinfo/install/addon_error_prefs.py
+++ b/stampinfo/install/addon_error_prefs.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -19,19 +19,23 @@
add-on global preferences
"""
+import sys
+
import bpy
from bpy.types import AddonPreferences
from bpy.props import BoolProperty, StringProperty
from ..ui.dependencies_ui import drawDependencies
-import sys
+from stampinfo.config import sm_logging
+
+_logger = sm_logging.getLogger(__name__)
class UAS_StampInfo_AddonErrorPrefs(AddonPreferences):
"""
- Use this to get these prefs:
- prefs = context.preferences.addons["stampinfo"].preferences
+ Use this to get these prefs:
+ prefs = context.preferences.addons["stampinfo"].preferences
"""
# this must match the add-on name, use '__package__'
@@ -49,13 +53,16 @@ class UAS_StampInfo_AddonErrorPrefs(AddonPreferences):
# ------------------------------
install_failed: BoolProperty(
- name="Install Failed", default=True,
+ name="Install Failed",
+ default=True,
)
error_message: StringProperty(
- name="Error Message", default="",
+ name="Error Message",
+ default="",
)
verbose: BoolProperty(
- name="Verbose", default=False,
+ name="Verbose",
+ default=False,
)
##################################################################################
@@ -128,17 +135,14 @@ def draw(self, context):
def register():
+ _logger.debug_ext(" - Registering Addon Error Prefs Package", form="REG")
+
for cls in _classes:
bpy.utils.register_class(cls)
- prefs_addon = bpy.context.preferences.addons["stampinfo"].preferences
- if prefs_addon.verbose:
- print(" - Registering Add-on Installation Error Preferences\n")
-
def unregister():
- prefs_addon = bpy.context.preferences.addons["stampinfo"].preferences
- if prefs_addon.verbose:
- print(" - Unregistering Add-on Installation Error Preferences")
+ _logger.debug_ext(" - Unregistering Addon Error Prefs Package", form="UNREG")
+
for cls in reversed(_classes):
bpy.utils.unregister_class(cls)
diff --git a/stampinfo/install/install_dependencies.py b/stampinfo/install/install_dependencies.py
index 9c61692..10a90c3 100644
--- a/stampinfo/install/install_dependencies.py
+++ b/stampinfo/install/install_dependencies.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -23,9 +23,9 @@
from ..utils.utils_os import internet_on, module_can_be_imported, is_admin
from . import addon_error_prefs
-import logging
+from stampinfo.config import sm_logging
-_logger = logging.getLogger(__name__)
+_logger = sm_logging.getLogger(__name__)
def install_library(lib_names, pip_retries=2, pip_timeout=-100):
diff --git a/stampinfo/operators/debug.py b/stampinfo/operators/debug.py
index 8ad98f7..9897c79 100644
--- a/stampinfo/operators/debug.py
+++ b/stampinfo/operators/debug.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -27,9 +27,9 @@
from ..config import config
from ..utils import utils_render
-import logging
+from stampinfo.config import sm_logging
-_logger = logging.getLogger(__name__)
+_logger = sm_logging.getLogger(__name__)
class UAS_Stamp_Info_OT_EnableDebug(Operator):
@@ -86,10 +86,14 @@ def draw(self, context):
def register():
+ _logger.debug_ext(" - Registering Debug Package", form="REG")
+
for cls in _classes:
bpy.utils.register_class(cls)
def unregister():
+ _logger.debug_ext(" - Unregistering Debug Package", form="UNREG")
+
for cls in reversed(_classes):
bpy.utils.unregister_class(cls)
diff --git a/stampinfo/operators/render_operators.py b/stampinfo/operators/render_operators.py
index ee2a8e1..33903c4 100644
--- a/stampinfo/operators/render_operators.py
+++ b/stampinfo/operators/render_operators.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -33,6 +33,10 @@
from stampinfo import stamper
from ..config import config
+from stampinfo.config import sm_logging
+
+_logger = sm_logging.getLogger(__name__)
+
class UAS_PT_StampInfo_Render(Operator):
bl_idname = "uas_stampinfo.render"
@@ -181,7 +185,10 @@ def execute(self, context):
+ ".png"
)
stampInfoSettings.renderTmpImageWithStampedInfo(
- scene, renderFrame, renderPath=tempFramedRenderPath, renderFilename=tempFramedRenderFilenameStill,
+ scene,
+ renderFrame,
+ renderPath=tempFramedRenderPath,
+ renderFilename=tempFramedRenderFilenameStill,
)
elif "ANIMATION" == self.renderMode:
@@ -300,10 +307,14 @@ def execute(self, context):
def register():
+ _logger.debug_ext(" - Registering Render Operators Package", form="REG")
+
for cls in _classes:
bpy.utils.register_class(cls)
def unregister():
+ _logger.debug_ext(" - Unregistering Render Operators Package", form="UNREG")
+
for cls in reversed(_classes):
bpy.utils.unregister_class(cls)
diff --git a/stampinfo/properties/stampInfoSettings.py b/stampinfo/properties/stampInfoSettings.py
index fafe21e..eef4e2a 100644
--- a/stampinfo/properties/stampInfoSettings.py
+++ b/stampinfo/properties/stampInfoSettings.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -19,21 +19,20 @@
General settings
"""
-import os
+# import os
from pathlib import Path
from stampinfo import stamper
import bpy
from bpy.props import StringProperty, BoolProperty, IntProperty, FloatProperty, EnumProperty
+from stampinfo import config
from stampinfo import infoImage
from stampinfo.utils import utils
-import logging
+from stampinfo.config import sm_logging
-_logger = logging.getLogger(__name__)
-
-# from stampinfo.__init__ import bl_info
+_logger = sm_logging.getLogger(__name__)
# global vars
if "gbWkDebug" not in vars() and "gbWkDebug" not in globals():
@@ -56,10 +55,10 @@
class UAS_StampInfoSettings(bpy.types.PropertyGroup):
def version(self):
- """ Return the add-on version in the form of a tupple made by:
- - a string x.y.z (eg: "1.21.3")
- - an integer. x.y.z becomes xxyyyzzz (eg: "1.21.3" becomes 1021003)
- Return None if the addon has not been found
+ """Return the add-on version in the form of a tupple made by:
+ - a string x.y.z (eg: "1.21.3")
+ - an integer. x.y.z becomes xxyyyzzz (eg: "1.21.3" becomes 1021003)
+ Return None if the addon has not been found
"""
return utils.addonVersion("Stamp Info")
@@ -224,7 +223,9 @@ def buildLogosList(self, context):
# ---------- shared settings ---------
animRangeUsed: BoolProperty(
- name="Frame Range", description="Stamp the range of the animation, in frames", default=True,
+ name="Frame Range",
+ description="Stamp the range of the animation, in frames",
+ default=True,
)
handlesUsed: BoolProperty(
name="Frame Handles",
@@ -296,7 +297,10 @@ def buildLogosList(self, context):
# used by production scripts to specify another file than the current one
# if set to "" then it is ignored and the current file name is used
customFileFullPath: StringProperty(
- name="Custom File Name", description="Enter a path and name of the file to display", default="", options=set(),
+ name="Custom File Name",
+ description="Enter a path and name of the file to display",
+ default="",
+ options=set(),
)
# ---------- shot manager -------------
@@ -320,7 +324,11 @@ def buildLogosList(self, context):
)
shotHandles: IntProperty(
- name="Shot Handles Duration", description="Duration of the handles of the shot", default=10, min=0, soft_max=50,
+ name="Shot Handles Duration",
+ description="Duration of the handles of the shot",
+ default=10,
+ min=0,
+ soft_max=50,
)
# ---------- Camera properties -------------
diff --git a/stampinfo/stamper.py b/stampinfo/stamper.py
index df3a1e6..dd692a0 100644
--- a/stampinfo/stamper.py
+++ b/stampinfo/stamper.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -24,9 +24,9 @@
import bpy
import bpy.utils.previews
-import logging
+from stampinfo.config import sm_logging
-_logger = logging.getLogger(__name__)
+_logger = sm_logging.getLogger(__name__)
def getRenderRange(scene):
@@ -36,8 +36,7 @@ def getRenderRange(scene):
# wk fix: now retunrs an array of ints!
def getRenderResolution(scene):
- """Get the current scene rendered image output resolution as float tupple (not int !) and with taking into account the render percentage
- """
+ """Get the current scene rendered image output resolution as float tupple (not int !) and with taking into account the render percentage"""
renderResolution = (
scene.render.resolution_x * scene.render.resolution_percentage * 0.01,
scene.render.resolution_y * scene.render.resolution_percentage * 0.01,
@@ -115,8 +114,7 @@ def evaluateRenderResolutionForStampInfo(imageRes, resPercentage=100):
def getInnerHeight(scene):
- """Get the height (integer) in pixels of the image between the 2 borders according to the current mode
- """
+ """Get the height (integer) in pixels of the image between the 2 borders according to the current mode"""
innerH = -1
if "OVER" == scene.UAS_StampInfo_Settings.stampInfoRenderMode:
@@ -216,7 +214,7 @@ def getInfoFileFullPath(scene, renderFrameInd=None):
def getStampInfoRenderFilepath(scene, useTempDir=False):
"""Get a functional render file path to render the temporary files
-
+
Returns: If the file is not saved and the path is relative then a temporary file path is returned
"""
filepath = scene.render.filepath
@@ -235,8 +233,7 @@ def getTempBGImageBaseName():
def createTempBGImage(scene):
- """Create the temporaty image used to set the render size (not the one with the stamped info)
- """
+ """Create the temporaty image used to set the render size (not the one with the stamped info)"""
from PIL import Image
print("\n createTempBGImage ")
@@ -274,8 +271,7 @@ def deleteTempImage(scene):
def deletePreviousInfoImage(scene, currentFrame):
- """Delete only the info image file rendered in the previous frame
- """
+ """Delete only the info image file rendered in the previous frame"""
print("\n deletePreviousInfoImage [ ")
rangeStart = getRenderRange(scene)[0]
diff --git a/stampinfo/ui/__init__.py b/stampinfo/ui/__init__.py
index 23b95cc..b0662d2 100644
--- a/stampinfo/ui/__init__.py
+++ b/stampinfo/ui/__init__.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -24,8 +24,14 @@
# from . import si_ui
+from stampinfo.config import sm_logging
+
+_logger = sm_logging.getLogger(__name__)
+
def register():
+ _logger.debug_ext(" - Registering UI Package", form="REG")
+
about.register()
prefs.register()
@@ -34,6 +40,8 @@ def register():
def unregister():
+ _logger.debug_ext(" - Unregistering UI Package", form="UNREG")
+
# si_ui.unregister()
prefs.unregister()
about.unregister()
diff --git a/stampinfo/ui/about.py b/stampinfo/ui/about.py
index 0c8ea62..ff40329 100644
--- a/stampinfo/ui/about.py
+++ b/stampinfo/ui/about.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -25,6 +25,10 @@
from ..ui.dependencies_ui import drawDependencies
from ..utils.utils import addonCategory
+from stampinfo.config import sm_logging
+
+_logger = sm_logging.getLogger(__name__)
+
class UAS_StampInfo_OT_About(Operator):
bl_idname = "uas_stamp_info.about"
@@ -102,10 +106,14 @@ def execute(self, context):
def register():
+ _logger.debug_ext(" - Registering About Package", form="REG")
+
for cls in _classes:
bpy.utils.register_class(cls)
def unregister():
+ _logger.debug_ext(" - Unregistering About Package", form="UNREG")
+
for cls in reversed(_classes):
bpy.utils.unregister_class(cls)
diff --git a/stampinfo/ui/dependencies_ui.py b/stampinfo/ui/dependencies_ui.py
index ebe266a..3b78504 100644
--- a/stampinfo/ui/dependencies_ui.py
+++ b/stampinfo/ui/dependencies_ui.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/stampinfo/ui/prefs.py b/stampinfo/ui/prefs.py
index bf133c8..8202d5f 100644
--- a/stampinfo/ui/prefs.py
+++ b/stampinfo/ui/prefs.py
@@ -22,6 +22,10 @@
import bpy
from bpy.types import Menu
+from stampinfo.config import sm_logging
+
+_logger = sm_logging.getLogger(__name__)
+
#############
# Preferences
@@ -63,10 +67,14 @@ def draw(self, context):
def register():
+ _logger.debug_ext(" - Registering Prefs Package", form="REG")
+
for cls in _classes:
bpy.utils.register_class(cls)
def unregister():
+ _logger.debug_ext(" - Unregistering Prefs Package", form="UNREG")
+
for cls in reversed(_classes):
bpy.utils.unregister_class(cls)
diff --git a/stampinfo/ui/si_ui.py b/stampinfo/ui/si_ui.py
index c2d6ff9..d40d583 100644
--- a/stampinfo/ui/si_ui.py
+++ b/stampinfo/ui/si_ui.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
Main panel UI
"""
-import logging
+from stampinfo.config import sm_logging
import bpy
import bpy.utils.previews
@@ -39,7 +39,7 @@
from stampinfo.operators import debug
-_logger = logging.getLogger(__name__)
+_logger = sm_logging.getLogger(__name__)
importlib.reload(stampInfoSettings)
@@ -70,6 +70,7 @@ def draw_header(self, context):
row.operator("uas_stamp_info.about", text="", icon_value=icon.icon_id)
def draw_header_preset(self, context):
+ prefs = context.preferences.addons["stampinfo"].preferences
layout = self.layout
layout.emboss = "NONE"
row = layout.row(align=True)
@@ -96,6 +97,12 @@ def draw_header_preset(self, context):
row.separator(factor=2)
row.menu("UAS_MT_StampInfo_prefs_mainmenu", icon="PREFERENCES", text="")
+ if prefs.newAvailableVersion:
+ row.separator(factor=0.5)
+ subRow = row.row()
+ subRow.alert = True
+ subRow.operator("uas_shot_manager.update_dialog", text="", icon="WORLD_DATA")
+
row.separator(factor=1.0)
def draw(self, context):
@@ -695,10 +702,14 @@ def module_can_be_imported(name):
def register():
+ _logger.debug_ext(" - Registering Main UI Package", form="REG")
+
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
+ _logger.debug_ext(" - Unregistering Main UI Package", form="UNREG")
+
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
diff --git a/stampinfo/utils/utils.py b/stampinfo/utils/utils.py
index 0456f04..d0a0687 100644
--- a/stampinfo/utils/utils.py
+++ b/stampinfo/utils/utils.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -28,22 +28,20 @@
import os
-import logging
+from stampinfo.config import sm_logging
-_logger = logging.getLogger(__name__)
+_logger = sm_logging.getLogger(__name__)
def convertVersionStrToInt(versionStr):
- """ Convert a string formated like "1.23.48" to a version integer such as 1023048
- """
+ """Convert a string formated like "1.23.48" to a version integer such as 1023048"""
formatedVersion = "{:02}{:03}{:03}"
versionSplitted = versionStr.split(".")
return int(formatedVersion.format(int(versionSplitted[0]), int(versionSplitted[1]), int(versionSplitted[2])))
def convertVersionIntToStr(versionInt):
- """ Convert an integer formated like 1023048 to a version string such as "1.23.48"
- """
+ """Convert an integer formated like 1023048 to a version string such as "1.23.48" """
versionIntStr = str(versionInt)
length = len(versionIntStr)
versionStr = (
@@ -57,10 +55,10 @@ def convertVersionIntToStr(versionInt):
def addonVersion(addonName):
- """ Return the add-on version in the form of a tupple made by:
- - a string x.y.z (eg: "1.21.3")
- - an integer. x.y.z becomes xxyyyzzz (eg: "1.21.3" becomes 1021003)
- Return None if the addon has not been found
+ """Return the add-on version in the form of a tupple made by:
+ - a string x.y.z (eg: "1.21.3")
+ - an integer. x.y.z becomes xxyyyzzz (eg: "1.21.3" becomes 1021003)
+ Return None if the addon has not been found
"""
import addon_utils
@@ -90,17 +88,17 @@ def addonVersion(addonName):
return versions
-def display_addon_registered_version(addon_name):
+def display_addon_registered_version(addon_name, more_info=""):
versionTupple = addonVersion(addon_name)
if versionTupple is not None:
print(
- "\n*** *** Registering "
+ "\n*** *** Registering Ubisoft "
+ addon_name
+ " Add-on - version: "
+ versionTupple[0]
- + " ("
- + str(versionTupple[1])
- + ") *** ***"
+ + f" ({versionTupple[1]})"
+ + (f" - {more_info}" if more_info != "" else "")
+ + " *** ***"
)
else:
print('\n *** Cannot find registered version for add-on "' + addon_name + '" ***\n')
@@ -162,7 +160,9 @@ def openMedia(media_filepath, inExternalPlayer=False):
# bpy.ops.render.view_show()
bpy.ops.image.open(
- filepath=media_filepath, relative_path=False, show_multiview=False,
+ filepath=media_filepath,
+ relative_path=False,
+ show_multiview=False,
)
# bpy.data.images.[image_name].reload()
@@ -179,8 +179,8 @@ def openMedia(media_filepath, inExternalPlayer=False):
def add_background_video_to_cam(
camera: bpy.types.Camera, movie_path, frame_start, alpha=-1, proxyRenderSize="PROXY_50"
):
- """ Camera argument: use camera.data, not the camera object
- proxyRenderSize is PROXY_25, PROXY_50, PROXY_75, PROXY_100, FULL
+ """Camera argument: use camera.data, not the camera object
+ proxyRenderSize is PROXY_25, PROXY_50, PROXY_75, PROXY_100, FULL
"""
print("add_background_video_to_cam")
movie_path = Path(movie_path)
@@ -212,8 +212,7 @@ def add_background_video_to_cam(
def findFirstUniqueName(originalItem, name, itemsArray):
- """ Return a string that correspont to name.xxx as the first unique name in the array
- """
+ """Return a string that correspont to name.xxx as the first unique name in the array"""
itemInd = 0
numDuplicatesFound = 0
newIndexStr = ".{:03}"
@@ -229,8 +228,8 @@ def findFirstUniqueName(originalItem, name, itemsArray):
def getSceneVSE(vsm_sceneName, createVseTab=False):
- """ Return the scene that has the name held by vsm_sceneName and adds a VSE in it if there is not already one.
- Use .sequence_editor to get the vse of the scene
+ """Return the scene that has the name held by vsm_sceneName and adds a VSE in it if there is not already one.
+ Use .sequence_editor to get the vse of the scene
"""
vsm_scene = None
@@ -277,8 +276,7 @@ def getSceneVSE(vsm_sceneName, createVseTab=False):
def duplicateObject(sourceObject):
- """ Duplicate (deepcopy) an object and place it in the same collection
- """
+ """Duplicate (deepcopy) an object and place it in the same collection"""
newObject = sourceObject.copy()
newObject.animation_data.action = sourceObject.animation_data.action.copy()
newObject.data = sourceObject.data.copy()
@@ -290,4 +288,3 @@ def duplicateObject(sourceObject):
else:
(sourceObject.users_scene)[0].collection.objects.link(newObject)
return newObject
-
diff --git a/stampinfo/utils/utils_filenames.py b/stampinfo/utils/utils_filenames.py
index da27957..00aa036 100644
--- a/stampinfo/utils/utils_filenames.py
+++ b/stampinfo/utils/utils_filenames.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -23,6 +23,10 @@
from pathlib import Path
import bpy
+from stampinfo.config import sm_logging
+
+_logger = sm_logging.getLogger(__name__)
+
class SequencePath:
# to do:
@@ -32,7 +36,7 @@ class SequencePath:
# - support absolute and relative paths
"""
Split a file path into parts. Dedicated to sequence filename management.
-
+
Returns an instance made of:
- fullpath: the file path and name
- parent: the file path without the file name AND with a "\" at the end
@@ -40,7 +44,7 @@ class SequencePath:
- stem: the name of the file without extension
- seq_name: the name of the sequence when # are removed
- suffix: the file extension
-
+
When the initial sequence path and name is submitted with no extension then it is seen as a path
Eg.: myPath = SequencePath("c:\temp\mySequence_####.png")
@@ -326,10 +330,14 @@ def run_sequence_path_tests(at_frame=None):
def register():
+ _logger.debug_ext(" - Registering Filenames Package", form="REG")
+
for cls in _classes:
bpy.utils.register_class(cls)
def unregister():
+ _logger.debug_ext(" - Unregistering Filenames Package", form="UNREG")
+
for cls in reversed(_classes):
bpy.utils.unregister_class(cls)
diff --git a/stampinfo/utils/utils_inspectors.py b/stampinfo/utils/utils_inspectors.py
index 2a4a468..f6b5ad8 100644
--- a/stampinfo/utils/utils_inspectors.py
+++ b/stampinfo/utils/utils_inspectors.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/stampinfo/utils/utils_python.py b/stampinfo/utils/utils_python.py
new file mode 100644
index 0000000..d1ba1c4
--- /dev/null
+++ b/stampinfo/utils/utils_python.py
@@ -0,0 +1,32 @@
+# GPLv3 License
+#
+# Copyright (C) 2022 Ubisoft
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""
+Functions useful in a generic context
+"""
+
+
+def copyString(str1):
+ resStr = ""
+ for c in str1:
+ resStr += c
+ return resStr
+
+
+def asciiColor(r, g, b):
+ """Convert rgb values to ascii color string"""
+ return f"\33[38;2;{r};{g};{b}m"
diff --git a/stampinfo/utils/utils_render.py b/stampinfo/utils/utils_render.py
index c62ffa3..f79298a 100644
--- a/stampinfo/utils/utils_render.py
+++ b/stampinfo/utils/utils_render.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -25,9 +25,9 @@
import bpy
from bpy.types import Operator
-import logging
+from stampinfo.config import sm_logging
-_logger = logging.getLogger(__name__)
+_logger = sm_logging.getLogger(__name__)
def isRenderPathValid(scene):
@@ -47,7 +47,7 @@ def getRenderOutputFilename(scene, fileNameOnly=False):
outputFiles = list()
filePath = bpy.path.abspath(scene.render.filepath)
-
+
# print("\n *** images defs:")
# print(f" From {scene.frame_start} to {scene.frame_end} by {scene.frame_step}")
@@ -118,4 +118,3 @@ def execute(self, context):
# bpy.ops.render.opengl ( animation = True )
return {"FINISHED"}
-
diff --git a/stampinfo/utils/utils_ui.py b/stampinfo/utils/utils_ui.py
index 4152b3d..6b7ec68 100644
--- a/stampinfo/utils/utils_ui.py
+++ b/stampinfo/utils/utils_ui.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -34,23 +34,52 @@
from .utils_os import open_folder
+from stampinfo.config import sm_logging
+
+_logger = sm_logging.getLogger(__name__)
+
+
###################
# UI
###################
def collapsable_panel(
- layout: bpy.types.UILayout, data: bpy.types.AnyType, property: str, alert: bool = False, **kwargs
+ layout: bpy.types.UILayout,
+ data: bpy.types.AnyType,
+ property: str,
+ alert: bool = False,
+ text=None,
):
- row = layout.row()
+ """Draw an arrow to collapse or extend a panel.
+ Return the title row
+ Args:
+ layout: parent component
+ data: the object with the properties
+ property: the boolean used to store the rolled-down state of the panel
+ alert: is the title bar of the panel is drawn in alert mode
+ text: the title of the panel
+ eg: collapsable_panel(layout, addon_props, "display_users", text="Server Users")
+ if addon_props.addonPrefs_ui_expanded: ...
+ """
+ row = layout.row(align=True)
+ row.alignment = "LEFT"
+ # row.scale_x = 0.9
+ row.alert = alert
row.prop(
- data, property, icon="TRIA_DOWN" if getattr(data, property) else "TRIA_RIGHT", icon_only=True, emboss=False,
+ data,
+ property,
+ icon="TRIA_DOWN" if getattr(data, property) else "TRIA_RIGHT",
+ icon_only=True,
+ emboss=False,
+ text=text,
)
if alert:
- row.alert = True
row.label(text="", icon="ERROR")
- row.label(**kwargs)
- return getattr(data, property)
+ # row.label(text=text)
+ row.alert = False
+
+ return row
###################
@@ -228,14 +257,75 @@ def execute(self, context):
####################################################################
-_classes = (UAS_StampInfo_OpenExplorer, UAS_OT_Open_Documentation_Url, UAS_OpenFileBrowser, UAS_StampInfo_OT_Querybox)
+
+class UAS_ShotManager_UpdateDialog(Operator):
+ bl_idname = "uas_shot_manager.update_dialog"
+ bl_label = "Add-on Update Available"
+ bl_description = "Open a dialog window presenting the available update of the add-on"
+
+ # can be a web url or an intranet path
+ url: StringProperty(default="")
+
+ addonName: StringProperty(default="")
+
+ def invoke(self, context, event):
+ self.addonName = "Ubisoft Stamp Info"
+ self.url = "https://github.com/ubisoft/stampinfo/releases/latest"
+
+ return context.window_manager.invoke_props_dialog(self, width=450)
+
+ def draw(self, context):
+ prefs = context.preferences.addons["stampinfo"].preferences
+
+ layout = self.layout
+ box = layout.box()
+ col = box.column()
+
+ sepRow = col.row()
+ sepRow.separator(factor=0.5)
+
+ row = col.row()
+ newVersionStr = f"V. {convertVersionIntToStr(prefs.newAvailableVersion)}"
+ row.label(text=f"A new version of {self.addonName} is available on GitHub: {newVersionStr}")
+
+ sepRow = col.row()
+ sepRow.separator(factor=0.5)
+
+ row = col.row()
+ row.label(text="You can download it here:")
+
+ doc_op = row.operator("stampinfo.open_documentation_url", text="Download Latest", icon="URL")
+ doc_op.path = self.url
+ doc_op.tooltip = "Open latest Stamp Info download page: " + doc_op.path
+
+ sepRow = col.row()
+ sepRow.separator(factor=0.5)
+
+ def execute(self, context):
+ return {"FINISHED"}
+
+
+####################################################################
+
+
+_classes = (
+ UAS_StampInfo_OpenExplorer,
+ UAS_OT_Open_Documentation_Url,
+ UAS_OpenFileBrowser,
+ UAS_StampInfo_OT_Querybox,
+ UAS_ShotManager_UpdateDialog,
+)
def register():
+ _logger.debug_ext(" - Registering Utils UI Package", form="REG")
+
for cls in _classes:
bpy.utils.register_class(cls)
def unregister():
+ _logger.debug_ext(" - Unregistering Utils UI Package", form="UNREG")
+
for cls in reversed(_classes):
bpy.utils.unregister_class(cls)
diff --git a/stampinfo/utils/utils_vse_render.py b/stampinfo/utils/utils_vse_render.py
index efba8a3..0ddbc96 100644
--- a/stampinfo/utils/utils_vse_render.py
+++ b/stampinfo/utils/utils_vse_render.py
@@ -1,6 +1,6 @@
# GPLv3 License
#
-# Copyright (C) 2021 Ubisoft
+# Copyright (C) 2022 Ubisoft
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -35,6 +35,11 @@
from ..utils import utils
+from stampinfo.config import sm_logging
+
+_logger = sm_logging.getLogger(__name__)
+
+
# # ------------------------------------------------------------------------#
# # VSE tool Panel #
# # ------------------------------------------------------------------------#
@@ -1016,6 +1021,8 @@ def compositeVideoInVSE(
def register():
+ _logger.debug_ext(" - Registering Utils VSE Render Package", form="REG")
+
for cls in _classes:
bpy.utils.register_class(cls)
@@ -1025,6 +1032,8 @@ def register():
def unregister():
+ _logger.debug_ext(" - Unregistering Utils VSE Render Package", form="UNREG")
+
del bpy.types.WindowManager.stampinfo_vse_render
bpy.utils.unregister_class(UAS_VSE_OpenFileBrowser)