import asyncio import sys import bpy import math from mathutils import Vector, Matrix from contextlib import suppress def ui_refresh_properties(): # Refreshes the properties panel for windowManager in bpy.data.window_managers: for window in windowManager.windows: for area in window.screen.areas: if area.type == 'PROPERTIES': area.tag_redraw() def ui_refresh_view_3d(): # Refreshes the view 3D panel for windowManager in bpy.data.window_managers: for window in windowManager.windows: for area in window.screen.areas: if area.type == 'VIEW_3D': area.tag_redraw() def ui_refresh_all(): if not hasattr(bpy.data, "window_managers"): return # Refreshes all panels for windowManager in bpy.data.window_managers: for window in windowManager.windows: for area in window.screen.areas: area.tag_redraw() def reprint(*x): # This prints a message in the same console line continuously sys.stdout.write("\r" + " ".join(x)) sys.stdout.flush() def set_active(obj): obj.select_set(True) obj.hide_set(False) bpy.context.view_layer.objects.active = obj def mat3_to_vec_roll(mat): vecmat = vec_roll_to_mat3(mat.col[1], 0) vecmatinv = vecmat.inverted() rollmat = vecmatinv @ mat roll = math.atan2(rollmat[0][2], rollmat[2][2]) return roll def vec_roll_to_mat3(vec, roll): target = Vector((0, 0.1, 0)) nor = vec.normalized() axis = target.cross(nor) if axis.dot(axis) > 0.0000000001: axis.normalize() theta = target.angle(nor) bMatrix = Matrix.Rotation(theta, 3, axis) else: updown = 1 if target.dot(nor) > 0 else -1 bMatrix = Matrix.Scale(updown, 3) bMatrix[2][2] = 1.0 rMatrix = Matrix.Rotation(roll, 3, nor) mat = rMatrix @ bMatrix return mat async def cancel_gen(agen): """ Stops an asynchronous generator from outside. :param agen: The asynchronous generator :return: """ task = asyncio.create_task(agen.__anext__()) task.cancel() with suppress(Exception): await task await agen.aclose()