Files
avatechai-avatar-graph-comfyui/blender/ops_modify_shape_key.py
T
2023-09-26 18:21:52 +08:00

135 lines
5.0 KiB
Python

import blender_node
class Mesh_ModifyShapeKey(blender_node.ObjectOps):
CUSTOM_NAME = "Modify Shape Key"
EXTRA_INPUT_TYPES = {
"shape_key_name": ("STRING", {
# True if you want the field to look like the one on the ClipTextEncode node
"multiline": False,
"default": "EyeBlinkLeft", # default value
}),
"target_vertex_group": ("STRING", {
"multiline": False,
"default": ""
}),
"scale_x": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01, "display": "number"}),
"scale_y": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01, "display": "number"}),
"offset_x": ("FLOAT", {"default": 0.0, "min": -10.0, "max": 10.0, "step": 0.01, "display": "number"}),
"offset_y": ("FLOAT", {"default": 0.0, "min": -10.0, "max": 10.0, "step": 0.01, "display": "number"}),
"rotate": ("FLOAT", {"default": 0, "min": -360, "max": 360.0, "step": 0.01, "display": "number"}),
"origin_offset_x": ("FLOAT", {"default": 0, "min": -10.0, "max": 10.0, "step": 0.01, "display": "number"}),
"origin_offset_y": ("FLOAT", {"default": 0, "min": -10.0, "max": 10.0, "step": 0.01, "display": "number"}),
"transform_radius": ("FLOAT", {"default": 1.0, "min": 0, "max": 1, "step": 0.01, "display": "number"}),
"falloff": ("FLOAT", {"default": 0, "min": -10.0, "max": 10.0, "step": 0.01, "display": "number"}),
}
def blender_process(self, bpy, BPY_OBJ, shape_key_name, target_vertex_group, scale_x, scale_y, offset_x, offset_y, rotate, origin_offset_x, origin_offset_y, transform_radius, falloff):
from mathutils import Vector, Matrix
import math
obj = BPY_OBJ
# Create new shape key if its not in the object
if shape_key_name not in BPY_OBJ.data.shape_keys.key_blocks:
BPY_OBJ.shape_key_add(name=shape_key_name, from_mix=True)
# get shape key
sk = obj.data.shape_keys.key_blocks[shape_key_name]
# print(obj, sk)
# sk.interpolation = 'KEY_LINEAR'
verts = obj.data.vertices
# Create a new array of verts with sk as co and verts' groups
new_verts = []
for i, vert in enumerate(verts):
# print(i)
# print(sk.data[i].co)
new_vert = {
'co': sk.data[i].co,
'groups': vert.groups
}
new_verts.append(new_vert)
verts = new_verts
# get vertex group
# get the verts in the group
if target_vertex_group == '':
verts_in_group = verts
else:
vertex_group = obj.vertex_groups[target_vertex_group]
verts_in_group = [v for v in verts if vertex_group.index in [
vg.group for vg in v['groups']]]
center = sum((vert['co'] for vert in verts_in_group),
Vector()) / len(verts_in_group)
# apply origin offset
center.x += origin_offset_x
center.y += origin_offset_y
# Calculate max distance from center to any vertex in the group
max_distance = max(
(vert['co'] - center).length for vert in verts_in_group)
# Position each vert
for i, vert in enumerate(verts):
# return if vert is not in group
if target_vertex_group != '' and vertex_group.index not in [vg.group for vg in vert['groups']]:
continue
# Get vector from center to vertex
vec = vert['co'] - center
# Calculate distance from origin and weight factor
distance = vec.length
# weight = max(0, 1 - distance / (max_distance * transform_radius))
# if the vertex is outside the transform radius, skip it
if (distance / max_distance) > transform_radius:
continue
# calculate weight
weight = max(0, 1 - distance /
(transform_radius * max_distance)) * falloff
weight = min(weight, 1)
# print(scale_x, scale_y, weight)
# Scale vector
vec.x *= scale_x + (abs(scale_x - 1) * weight)
vec.y *= scale_y + (abs(scale_y - 1) * weight)
# # Offset vector
vec.x += offset_x + (abs(scale_x - 1) * weight)
vec.y += offset_y + (abs(scale_y - 1) * weight)
# Rotate vector
# rotate_right_rad = math.radians(rotate_right)
rotate_rad = math.radians(rotate)
# Create rotation matrices for the right and left rotations
# rotation_matrix_right = Matrix.Rotation(rotate_right_rad, 4, 'X')
rotation_matrix = Matrix.Rotation(rotate_rad, 4, 'Z')
# Apply the rotation matrices to the vector
# vec.rotate(rotation_matrix_right)
vec.rotate(rotation_matrix)
# Calculate new position
new_pos = center + vec
# Apply new position
# print(i, vert['co'], new_pos, weight)
sk.data[i].co = new_pos