2025-12-01
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
# SPDX-FileCopyrightText: 2025 Blender Studio Tools Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import bpy
|
||||
from mathutils import Vector
|
||||
from typing import List, Tuple
|
||||
|
||||
|
||||
def clamp(val, _min=0, _max=1) -> float or int:
|
||||
if val < _min:
|
||||
return _min
|
||||
if val > _max:
|
||||
return _max
|
||||
return val
|
||||
|
||||
|
||||
def get_lattice_vertex_index(lattice: bpy.types.Lattice, xyz: List[int], do_clamp=True) -> int:
|
||||
"""Get the index of a lattice vertex based on its position on the XYZ axes."""
|
||||
|
||||
# The lattice vertex indicies start in the -Y, -X, -Z corner,
|
||||
# increase on X+, then moves to the next row on Y+, then moves up on Z+.
|
||||
res_x, res_y, res_z = lattice.points_u, lattice.points_v, lattice.points_w
|
||||
x, y, z = xyz[:]
|
||||
if do_clamp:
|
||||
x = clamp(x, 0, res_x)
|
||||
y = clamp(y, 0, res_y)
|
||||
z = clamp(z, 0, res_z)
|
||||
|
||||
assert x < res_x and y < res_y and z < res_z, "Error: Lattice vertex xyz index out of bounds"
|
||||
|
||||
index = (z * res_y * res_x) + (y * res_x) + x
|
||||
return index
|
||||
|
||||
|
||||
def get_lattice_vertex_xyz_position(lattice: bpy.types.Lattice, index: int) -> (int, int, int):
|
||||
res_x, res_y, res_z = lattice.points_u, lattice.points_v, lattice.points_w
|
||||
|
||||
x = 0
|
||||
remaining = index
|
||||
z = int(remaining / (res_x * res_y))
|
||||
remaining -= z * (res_x * res_y)
|
||||
y = int(remaining / res_x)
|
||||
remaining -= y * res_x
|
||||
x = remaining # Maybe need to add or subtract 1 here?
|
||||
|
||||
return (x, y, z)
|
||||
|
||||
|
||||
def get_lattice_point_original_position(lattice: bpy.types.Lattice, index: int) -> Vector:
|
||||
"""Reset a lattice vertex to its original position."""
|
||||
start_vec = Vector((-0.5, -0.5, -0.5))
|
||||
if lattice.points_u == 1:
|
||||
start_vec[0] = 0
|
||||
if lattice.points_v == 1:
|
||||
start_vec[1] = 0
|
||||
if lattice.points_w == 1:
|
||||
start_vec[2] = 0
|
||||
|
||||
unit_u = 1 / (lattice.points_u - 0.99)
|
||||
unit_v = 1 / (lattice.points_v - 0.99)
|
||||
unit_w = 1 / (lattice.points_w - 0.99)
|
||||
|
||||
unit_vec = Vector((unit_u, unit_v, unit_w))
|
||||
xyz_vec = Vector(get_lattice_vertex_xyz_position(lattice, index))
|
||||
|
||||
return start_vec + xyz_vec * unit_vec
|
||||
|
||||
|
||||
def simple_driver(
|
||||
owner: bpy.types.ID,
|
||||
driver_path: str,
|
||||
target_ob: bpy.types.Object,
|
||||
data_path: str,
|
||||
array_index=-1,
|
||||
) -> bpy.types.Driver:
|
||||
if array_index > -1:
|
||||
owner.driver_remove(driver_path, array_index)
|
||||
driver = owner.driver_add(driver_path, array_index).driver
|
||||
else:
|
||||
owner.driver_remove(driver_path)
|
||||
driver = owner.driver_add(driver_path).driver
|
||||
|
||||
driver.expression = 'var'
|
||||
var = driver.variables.new()
|
||||
var.targets[0].id = target_ob
|
||||
var.targets[0].data_path = data_path
|
||||
|
||||
return driver
|
||||
|
||||
|
||||
def bounding_box(points) -> Tuple[Vector, Vector]:
|
||||
"""Return two vectors representing the lowest and highest coordinates of
|
||||
a the bounding box of the passed points.
|
||||
"""
|
||||
|
||||
lowest = points[0].copy()
|
||||
highest = points[0].copy()
|
||||
for p in points:
|
||||
for i in range(len(p)):
|
||||
if p[i] < lowest[i]:
|
||||
lowest[i] = p[i]
|
||||
if p[i] > highest[i]:
|
||||
highest[i] = p[i]
|
||||
|
||||
return lowest, highest
|
||||
|
||||
|
||||
def bounding_box_center(points) -> Vector:
|
||||
"""Find the bounding box center of some points."""
|
||||
bbox_low, bbox_high = bounding_box(points)
|
||||
return bbox_low + (bbox_high - bbox_low) / 2
|
||||
|
||||
|
||||
def bounding_box_center_of_objects(objects) -> Vector:
|
||||
"""Find the bounding box center of some objects."""
|
||||
all_points = []
|
||||
for o in objects:
|
||||
for p in o.bound_box:
|
||||
all_points.append(o.matrix_world @ Vector(p))
|
||||
return bounding_box_center(all_points)
|
||||
Reference in New Issue
Block a user