import math import bpy from ... import config from ...core import Check, Issue, contexts from ..general.objects import ModifiersCheck class LineartModifiersCheck(ModifiersCheck): """Same as the general modifier check, with lineart modifiers allowed.""" id = "modifiers_lineart" label = "Modifiers (lineart)" description = "No modifiers other than Line Art, Thickness, Subdivision Surface and Multiresolution." contexts = frozenset({contexts.CHAR_LINEART}) allowed_config_key = "ALLOWED_MODIFIERS_LINEART" def _color_settings(scene): """(key, label, getter, setter) of every color management setting.""" view = scene.view_settings return [ ("display_device", "Display device", lambda: scene.display_settings.display_device, lambda v: setattr(scene.display_settings, "display_device", v)), ("view_transform", "View transform", lambda: view.view_transform, lambda v: setattr(view, "view_transform", v)), ("look", "Look", lambda: view.look, lambda v: setattr(view, "look", v)), ("exposure", "Exposure", lambda: view.exposure, lambda v: setattr(view, "exposure", v)), ("gamma", "Gamma", lambda: view.gamma, lambda v: setattr(view, "gamma", v)), ("sequencer_colorspace", "Sequencer colorspace", lambda: scene.sequencer_colorspace_settings.name, lambda v: setattr(scene.sequencer_colorspace_settings, "name", v)), ("working_space", "Working space", lambda: getattr(getattr(bpy.data, "colorspace", None), "working_space", None), None), ] class ColorManagementCheck(Check): id = "color_management" label = "Color management" description = "Display, view transform, look, exposure, gamma and colorspaces follow the production specs." category = "Lineart" contexts = frozenset({contexts.CHAR_LINEART}) fix_description = "Apply the production color management (working space excepted)" def run(self, ctx): spec = config.COLOR_MANAGEMENT for key, label, getter, _setter in _color_settings(ctx.scene): expected = spec.get(key) if expected is None: continue value = getter() if isinstance(expected, float): ok = value is not None and math.isclose(value, expected, abs_tol=1e-6) else: ok = value == expected if not ok: yield Issue(f"{label} is '{value}', expected '{expected}'", data={"key": key}) def fix(self, ctx, issues): spec = config.COLOR_MANAGEMENT keys = {issue.data.get("key") for issue in issues} failed = [] for key, label, _getter, setter in _color_settings(ctx.scene): if key not in keys: continue if setter is None: failed.append(f"{label} must be changed by hand (it converts existing colors)") continue try: setter(spec[key]) except (TypeError, ValueError) as exc: failed.append(f"{label}: {exc}") return failed