Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy
- from ..properties.mlo import PortalProperties
- class PortalCreatorHelper:
- @classmethod
- def poll(cls, context):
- return get_selected_archetype(context) is not None and (context.active_object and context.active_object.mode == "EDIT")
- @staticmethod
- def sort_2d_coords_winding(coords: list[tuple[float, float]]):
- """Sort 4 2D points in a winding order."""
- # Thank you Pranav! https://stackoverflow.com/a/70624269/11903486
- np_coords = numpy.array(np_coords)
- centroid = numpy.sum(np_coords, axis=0) / np_coords.shape[0]
- vector_from_centroid = np_coords - centroid
- vector_angle = numpy.arctan2(
- vector_from_centroid[:, 1], vector_from_centroid[:, 0])
- # Find the indices that give a sorted vector_angle array
- sort_order = list(numpy.argsort(-vector_angle))
- # Apply sort_order to original pts array.
- return [coords[i] for i in sort_order]
- @staticmethod
- def is_coplanar(points: list[tuple[float, float, float]]):
- """Check if 4 3D points lie on the same plane."""
- leg1 = points[1] - points[0]
- leg2 = points[2] - points[0]
- leg3 = points[3] - points[0]
- return leg3.dot(leg1.cross(leg2)) == 0
- @staticmethod
- def get_screen_coords(coords_3d: list[tuple[float, float, float]]) -> list[tuple[float, float]]:
- """Get 2D screen coords of the provided 3d coords."""
- region = bpy.context.region
- region_3d = bpy.context.space_data.region_3d
- corners2d = []
- for corner in coords_3d:
- corners2d.append(location_3d_to_region_2d(
- region, region_3d, corner))
- return corners2d
- def get_selected_portal_verts(self, context):
- selected_verts = []
- for obj in context.objects_in_mode:
- selected_verts.extend(get_selected_vertices(obj))
- return selected_verts
- def selected_archetype_has_asset(self, context):
- selected_archetype = get_selected_archetype(context)
- if not selected_archetype.asset:
- self.message("You must select an asset.")
- return False
- def set_portal_corners_to_selected_verts(self, context, portal: PortalProperties, offset: tuple[float, float, float]):
- """Set portal corners to selected verts in winding order."""
- selected_verts = self.get_selected_portal_verts(context)
- if len(selected_verts) != 4:
- self.message("You must select exactly 4 vertices.")
- return False
- if not PortalCreatorHelper.is_coplanar(selected_verts):
- self.warning(
- "Selection of points are not coplanar. This may cause issues with the portal.")
- screen_coords = PortalCreatorHelper.get_screen_coords(selected_verts)
- screen_coords = PortalCreatorHelper.sort_2d_coords_winding(screen_coords)
- portal.corner1 = screen_coords[2] - offset
- portal.corner2 = screen_coords[1] - offset
- portal.corner3 = screen_coords[0] - offset
- portal.corner4 = screen_coords[3] - offset
- return True
- class SOLLUMZ_OT_create_portal_from_selection(PortalCreatorHelper, SOLLUMZ_OT_base, bpy.types.Operator):
- """Create a portal from selected verts"""
- bl_idname = "sollumz.createportalfromselection"
- bl_label = "Create Portal From Verts"
- def run(self, context):
- if not self.selected_archetype_has_asset():
- return False
- selected_archetype = get_selected_archetype(context)
- portal_offset = selected_archetype.asset.location
- new_portal = selected_archetype.new_portal()
- return self.set_portal_corners_to_selected_verts(context, new_portal, portal_offset)
- class SOLLUMZ_OT_update_portal_from_selection(PortalCreatorHelper, SOLLUMZ_OT_base, bpy.types.Operator):
- """Update a portal from selected verts"""
- bl_idname = "sollumz.updateportalfromselection"
- bl_label = "Update Portal From Verts"
- def run(self, context):
- if not self.selected_archetype_has_asset():
- return False
- selected_archetype = get_selected_archetype(context)
- selected_portal = get_selected_portal(context)
- portal_offset = selected_archetype.asset.location
- return self.set_portal_corners_to_selected_verts(context, selected_portal, portal_offset)
Advertisement
Add Comment
Please, Sign In to add comment