"""Production specs used by the checks. Every UPPERCASE value can be overridden by a studio JSON file, see ``apply_overrides`` (path set in the add-on preferences or through the ``WTD_SANITY_CONFIG`` environment variable). Checks must read values at run time (``config.FPS``), never copy them at import time, so overrides apply. Values marked TODO are placeholders waiting for the real production specs. """ import copy import json import os import sys # --------------------------------------------------------------------------- # # Scene / render # --------------------------------------------------------------------------- # FPS = 24 FPS_BASE = 1.0 RESOLUTION = (2048, 858) RESOLUTION_PERCENTAGE = 100 PIXEL_ASPECT = (1.0, 1.0) # Units. TODO: confirm with production (metric/meters assumed). UNIT_SYSTEM = "METRIC" UNIT_SCALE_LENGTH = 1.0 UNIT_LENGTH = "METERS" # Color management. TODO: colorspace still to be determined by production. # A value of None means "not checked". COLOR_MANAGEMENT = { "display_device": "sRGB", "view_transform": "Standard", "look": "None", "exposure": 0.0, "gamma": 1.0, "sequencer_colorspace": "sRGB", "working_space": None, # e.g. "Linear Rec.709" (Blender 5+). Check only, never auto-fixed. } # --------------------------------------------------------------------------- # # File names. TODO: replace with the real Libreflow/Kitsu naming. # Named group "asset" is used to guess the asset/character name. # --------------------------------------------------------------------------- # FILENAME_PATTERNS = { "GENERAL": r"^(?:prp|set|chr)_(?P[A-Za-z0-9]+)_(?:mod|lineart|shading)(?:_v\d{3})?\.blend$", "CHAR_MOD": r"^chr_(?P[A-Za-z0-9]+)_mod(?:_v\d{3})?\.blend$", "CHAR_LINEART": r"^chr_(?P[A-Za-z0-9]+)_(?:lineart|shading)(?:_v\d{3})?\.blend$", "LAYOUT": r"^(?Psq\d{3})_(?Psh\d{4})_layout(?:_v\d{3})?\.blend$", } # --------------------------------------------------------------------------- # # Naming # --------------------------------------------------------------------------- # # Body of a name after its prefix: snake_case or PascalCase tokens joined by "_". NAME_BODY_PATTERN = r"[A-Za-z0-9]+(?:_[A-Za-z0-9]+)*" # Object prefix per object type. Types not listed are not checked. OBJECT_PREFIXES = { "MESH": "GEO_", "CURVE": "CRV_", "SURFACE": "SRF_", "FONT": "TXT_", "EMPTY": "NUL_", "ARMATURE": "RIG_", "LATTICE": "LAT_", "GREASEPENCIL": "LA_", "CAMERA": "CAM_", "LIGHT": "LGT_", } # Prefix per bpy.data collection. DATABLOCK_PREFIXES = { "collections": "COL_", "materials": "MAT_", "node_groups": "NG_", } # Mesh datablocks must carry the same name as their (single) object. MESH_DATA_MATCHES_OBJECT = True # Blender default names that must never survive in a published file. DEFAULT_NAMES = { "cube", "plane", "sphere", "uvsphere", "icosphere", "cylinder", "cone", "torus", "circle", "grid", "suzanne", "monkey", "empty", "camera", "light", "lamp", "point", "sun", "spot", "area", "material", "collection", "beziercurve", "beziercircle", "nurbscurve", "nurbspath", "text", "armature", "lattice", "nodegroup", "geometrynodes", "stroke", "gpencil", "lineart", "scene", "world", "object", "mesh", } # --------------------------------------------------------------------------- # # Structure (placeholder, real hierarchy to be defined) # --------------------------------------------------------------------------- # # Collections that must exist. "{asset}" is replaced by the asset name. REQUIRED_COLLECTIONS = [] # --------------------------------------------------------------------------- # # Geometry # --------------------------------------------------------------------------- # MAX_FACE_SIDES = 4 # sin() of the reflex angle above which a corner counts as concave. CONCAVE_TOLERANCE = 1e-4 # Open borders are reported as non-manifold unless this is True. NON_MANIFOLD_ALLOW_BOUNDARY = False UV_NEGATIVE_TOLERANCE = 1e-6 # --------------------------------------------------------------------------- # # Objects # --------------------------------------------------------------------------- # ALLOWED_MODIFIERS = {"SUBSURF", "MULTIRES"} ALLOWED_MODIFIERS_LINEART = { "SUBSURF", "MULTIRES", "LINEART", "GREASE_PENCIL_THICKNESS", } # Which transform channels must be applied. APPLY_TRANSFORM = {"location": False, "rotation": True, "scale": True} APPLY_TRANSFORM_TYPES = {"MESH", "CURVE", "SURFACE", "FONT", "META"} TRANSFORM_TOLERANCE = 1e-5 # Object types that must not be present in asset files. FORBIDDEN_ASSET_OBJECT_TYPES = {"LIGHT", "CAMERA"} # --------------------------------------------------------------------------- # # Characters # --------------------------------------------------------------------------- # # Reference JSON exported from the master character (see panel > Export # Character Reference). Overridden by the add-on preferences or by the # WTD_CHAR_REFERENCE environment variable. CHAR_REFERENCE_PATH = "" # Name of the character body object. "{asset}" is the character name. CHAR_BODY_NAME = "GEO_{asset}_Body" # Name keywords that identify inner mouth / eye parts (case-insensitive). CHAR_PART_KEYWORDS = [ "eye", "iris", "pupil", "cornea", "sclera", "lid", "lash", "mouth", "teeth", "tooth", "tongue", "gum", "palate", ] # Vertex groups the body mesh must have. TODO: real list. CHAR_BODY_VERTEX_GROUPS = [] # --------------------------------------------------------------------------- # # Layout # --------------------------------------------------------------------------- # # Instanced collections matching this pattern are sets that must sit at the origin. SET_COLLECTION_PATTERN = r"^(?:SET|ENV|set|env)[_-]" # Version token in a file or folder name (Libreflow stores v001/ folders). VERSION_PATTERN = r"(?