import numpy as np from ... import config from ...core import Check, Issue, contexts from ...core.mesh import loop_polygon_index, polygon_arrays class UVCheck(Check): id = "uvs" label = "UVs" description = "Every mesh has a UV map and no UV coordinate is negative." category = "UVs" contexts = contexts.ASSET def run(self, ctx): for ob in ctx.objects("MESH"): me = ob.data if not len(me.polygons): continue if not me.uv_layers: yield Issue.for_id(f"{ob.name}: no UV map", ob) continue _, totals, _ = polygon_arrays(me) poly_of_loop = loop_polygon_index(totals) for layer in me.uv_layers: uv = np.empty(len(me.loops) * 2, dtype=np.float32) layer.uv.foreach_get("vector", uv) negative = (uv.reshape(-1, 2) < -config.UV_NEGATIVE_TOLERANCE).any(axis=1) if negative.any(): faces = np.unique(poly_of_loop[negative]) yield Issue.for_id( f"{ob.name}: UV map '{layer.name}' has negative UVs on {faces.size} face(s)", ob, elements=faces.tolist(), element_type="FACE", )