Salut,
La solution de tabou est sans aucun doute la plus simple et la meilleure, mais j’ai quand même essayé de le faire avec des sélections de polygones. Voici ce que ça donne (avec deux noeuds python):
La sélection du bas :
Pour modifier l’épaisseur du cadre, le but est de pouvoir faire une mise à l’échelle sur cet axe :
Afin que les points les plus bas restent à zero et que la mise à l’échelle s’effectue vers le haut.
‘bottom’ (en haut à gauche) est le tag de sélection de polygones. Il est relié au noeud python BoundingBox qui calcule la bounding box de la sélection (taille et centre).
Le centre est déplacé en fonction d’un vecteur (‘axis’), c’est le même fonctionnement que dans l’outil de sélection ou AxisCenter avec :
-1 = -100%
0 = 0%
0.5 = 50%
1 = 100%
Ici, il est relié à une constante (0, -1, 0) pour placer l’axe tout en bas de la bounding box en Y, et au milieu en X et en Z.
Maintenant que l’on a la taille et la position de la sélection, on peut modifier la composante qui nous intéresse.
Le bas du cadre reste toujours à la même position, on relie donc l’ancienne position à la nouvelle (‘pos’ -> ‘pos’).
Pour la taille, il faut décomposer le vecteur en 3 réels (Vector2Reals), garder les anciens X et Z et choisir notre taille en Y (la donnée utilisateur “Thickness Y”).
‘enable’ est relié à une constante qu’il est conseillé de mettre à False (pour désactiver l’xpresso) lors de modifications dans les connexions. Si, par exemple, le port ‘pos’ ou ‘size’ du noeud ‘TransformSelection’ n’est pas relié, c’est un vecteur (0, 0, 0) par défaut qui est pris en compte, ce qui n’est pas forcément souhaitable.
Pour la barre de droite :
Ici on place l’axe tout à droite, soit 100% en X = (1, 0, 0). Pour la position on divise par deux la longueur. Il n’y a pas besoin de soustraire la moitié de l’épaisseur étant donné que l’axe est à 100 % en X.
Le fichier : http://www.xsyann.com/fc4d/frame_xpresso.c4d.zip
J’ai ajouté un exemple avec un slider pour contrôler la taille d’une sélection de polygones sur notre ami Fred (avec son nez, restons correct ).
Avec l’axe en (0, 0, 1).
En ce qui concerne le python, pour calculer la bounding box :
Code PHP:
import c4d
def getPoints(obj, polygons):
points = dict([(point, obj.GetPoint(point)) for poly in polygons for point in [poly.a, poly.b, poly.c, poly.d]])
return points
def splitVectors(vectors):
x, y, z = [], [], []
for v in vectors:
x.append(v.x)
y.append(v.y)
z.append(v.z)
return x, y, z
def getBoundingBox(obj, points, axis):
x, y, z = splitVectors(points.values())
min_pos, max_pos = c4d.Vector(min(x), min(y), min(z)), c4d.Vector(max(x), max(y), max(z))
pos, size = (min_pos + max_pos) / 2.0, max_pos - min_pos
return pos + (axis ^ (size / 2.0)), size
def main():
global pos, size
obj = selection.GetObject()
bs = selection.GetBaseSelect()
selected = [obj.GetPolygon(i) for i, s in enumerate(bs.GetAll(obj.GetPolygonCount())) if s]
pos, size = getBoundingBox(obj, getPoints(obj, selected), axis)
Pour modifier une sélection de polygones :
Code PHP:
import c4d
DELTA = 0.01
def getPoints(obj, polygons):
points = dict([(point, obj.GetPoint(point)) for poly in polygons for point in [poly.a, poly.b, poly.c, poly.d]])
return points
def splitVectors(vectors):
x, y, z = [], [], []
for v in vectors:
x.append(v.x)
y.append(v.y)
z.append(v.z)
return x, y, z
def mapVector(v, w, func):
return c4d.Vector(func(v.x, w.x), func(v.y, w.y), func(v.z, w.z))
def getBoundingBox(obj, points):
x, y, z = splitVectors(points.values())
min_pos, max_pos = c4d.Vector(min(x), min(y), min(z)), c4d.Vector(max(x), max(y), max(z))
return (min_pos + max_pos) / 2.0, max_pos - min_pos
def transformPoints(obj, points, center, offset, scale):
for i, point in points.iteritems():
obj.SetPoint(i, ((point - center) ^ scale) + center + offset)
def transformPolygonSelection(obj, bs, pos, size, axis):
selected = [obj.GetPolygon(i) for i, s in enumerate(bs.GetAll(obj.GetPolygonCount())) if s]
points = getPoints(obj, selected)
center, poly_size = getBoundingBox(obj, points)
center += (axis ^ (poly_size / 2.0))
offset = pos - center
scale = mapVector(size, poly_size, lambda x, y: max(x, DELTA) / y)
transformPoints(obj, points, center, offset, scale)
obj.Message(c4d.MSG_UPDATE)
def main():
if not enable or not selection:
return
transformPolygonSelection(selection.GetObject(), selection.GetBaseSelect(), pos, size, axis)