Files
2026-03-17 14:58:51 -06:00

188 lines
5.2 KiB
Python

from bpy.types import PropertyGroup
from bpy.props import (
StringProperty,
IntProperty,
CollectionProperty,
PointerProperty,
)
import bpy, json
from .util import get_pretty_stack
class BlenderLog_Entry(PropertyGroup):
"""Container for storing information about a single metarig warning/error.
A CollectionProperty of CloudRigLogEntries are added to the armature datablock
in cloud_generator.register().
This CollectionProperty is then populated by a BlenderLog_Manager instance created by
CloudRig_Generator, which is created by the Generate operator.
"""
name: StringProperty(name="Name", description="Name of issue", default="")
category: StringProperty(
name="Category", description="For internal categorization of log entries", default=""
)
icon: StringProperty(name="Icon", description="Icon for this log entry", default='ERROR')
description: StringProperty(name="Description", description="Description of issue", default="")
pretty_stack: StringProperty(
name="Pretty Stack",
description="Stack trace in the code of where this log entry was added. For internal use only",
)
operator: StringProperty(
name="Operator", description="Operator that can fix the issue", default=''
)
op_kwargs: StringProperty(
name="Operator Arguments",
description="Keyword arguments that will be passed to the operator. This should be a string that can be eval()'d into a python dict",
default='',
)
op_text: StringProperty(
name="Operator Text",
description="Text to display on the operator button",
default='',
)
op_icon: StringProperty(
name="Operator Icon",
description="Icon to display on the operator button",
default='',
)
class BlenderLog_Category(PropertyGroup):
name: StringProperty()
icon: StringProperty()
active_log_index: IntProperty()
logs: CollectionProperty(type=BlenderLog_Entry)
@property
def active_log(self):
if self.active_log_index > len(self.logs) - 1:
return
return self.logs[self.active_log_index]
def get_index(self, log):
for i, l in enumerate(self.logs):
if l == log:
return i
def clear(self):
self.logs.clear()
self.active_log_index = 0
class BlenderLog_Manager(PropertyGroup):
"""Class to manage BlenderLog_Entry CollectionProperty on metarigs.
This class is instanced once per rig generation, by the CloudRig_Generator class.
"""
categories: CollectionProperty(type=BlenderLog_Category)
active_cat_index: IntProperty()
@property
def active_category(self):
if self.active_cat_index > len(self.categories) - 1:
return
return self.categories[self.active_cat_index]
@property
def active_log(self):
return self.active_category.active_log
@property
def all_logs(self):
for cat in self.categories:
for log in cat.logs:
yield log
def add(
self,
name: str,
*,
description="No description.",
icon='ERROR',
category="Uncategorized",
category_icon="",
operator='',
op_kwargs={},
op_text="",
op_icon="",
):
"""Low-level function to add a log entry to the metarig object's data."""
cat_entry = self.categories.get(category)
if not cat_entry:
cat_entry = self.categories.add()
cat_entry.name = category
cat_entry.icon = category_icon or icon
entry = cat_entry.logs.add()
entry.pretty_stack = get_pretty_stack()
entry.name = name
entry.description = description
entry.category = category
entry.icon = icon
entry.operator = operator
entry.op_kwargs = json.dumps(op_kwargs)
entry.op_text = op_text
entry.op_icon = op_icon
return entry
def remove(self, log):
removed = False
for cat in self.categories:
for other_log in cat.logs:
if log == other_log:
cat.logs.remove(cat.get_index(log))
removed = True
break
if removed:
break
if removed and len(cat.logs) == 0:
self.clear_category(cat.name)
def remove_active(self):
self.remove(self.active_log)
def remove_category(self, cat):
self.categories.remove(self.get_index(cat))
def get_category(self, cat_name: str):
for cat in self.categories:
if cat.name == cat_name:
return cat
def get_index(self, cat):
for i, c in enumerate(self.categories):
if c == cat:
return i
def clear_category(self, cat_name: str):
cat = self.get_category(cat_name)
if cat:
cat.clear()
self.categories.remove(self.get_index(cat))
registry = [
BlenderLog_Entry,
BlenderLog_Category,
BlenderLog_Manager,
]
def register():
bpy.types.Scene.blender_log = PointerProperty(type=BlenderLog_Manager)
def unregister():
del bpy.types.Scene.blender_log