Salut la compagnie,
Existe-t-il un moyen de trier automatiquement la hiérarchie des objets dans le gestionnaire en fonction de différents paramètres ?
Je travaille actuellement avec des grilles de clones mograph assez importantes (aprox. entre 1000 et 10000 clones) avec un seul object source (sphère, cube, parfois spline) dont je fait varier positions et échelles avec différents effecteurs.
J'aurais besoin de trier ces clones (dans mograph ou après édition du cloner) en fonction de leur taille et / ou volume et / ou surface... voir de leur distance par rapport à un point donné.
Me retrouver en sortie avec par exemple un groupe d'objet dont le plus volumineux serait en haut de ma hiérarchie, et le moins volumineux en bas. Ou bien avec l'objet le plus proche de ma caméra en haut, et le plus éloigné en bas...
Une solution potentielle ?
D'avance merci !
Dernière modification par Helium ; 29/10/2018 à 17h24.
J'ai un début de piste qui me fait penser que c'est possible via un script. J'ai trouvé ce morceau de python qui classe les objets du gestionnaire par ordre alphabétique :
Je me dit que ça doit être tout à fait transposable à autre chose qu'un ordre alphabétique non ? J'essaie de bricoler l'une ou l'autre ligne, mais je pense que ce n'est pas aussi simple que ça, et de toute évidence je n'ai pas les connaissances requises...Code:# SORT OBJECTS ALPHABETICALLY IN OM import c4d from c4d import gui def main(): obj = doc.GetFirstObject() if not obj: return True doc.StartUndo() olist = [] while obj: olist.append([obj.GetName(),obj]) obj = obj.GetNext() olist.sort() olist.reverse() for i,o in enumerate(olist): doc.AddUndo(c4d.UNDOTYPE_CHANGE,o[1]) o[1].Remove() doc.InsertObject(o[1],None,None) c4d.EventAdd() doc.EndUndo() if __name__=='__main__': main()
Discussion à déplacer en section programmation peut être ducoup ?
Merci
Dernière modification par Helium ; 31/10/2018 à 11h04.
Interessant comme sujet...
Question bête:
tu n'as pas peur que ça flingue les priorités en cas d'animation.... ??
Je n'y ai pas pensé, mais c'est pour du statique, pas d'animation en vue. La finalité de tout ça est de récupérer un grand nombre de formes sur illustrator.
Pour info j'ai essayé de faire ça coté illustrator, j'ai trouvé un script qui ordonne des tracés en fonction de leur surface, mais au dessus d'une centaine d'objets il est dépassé...
Voici une version modifié de ton code qui classe par "taille".
Taille est entre guillemet car c'est juste une moyenne des valeurs de la boundingBox.
Attention que ce script reordonne tout les objets de l'OM.
il faudrait mettre une gestion de la hierarchie ou au moins une restriction à la selection
Code PHP:
# SORT OBJECTS ALPHABETICALLY IN OM
import c4d
from c4d import gui
def main():
obj = doc.GetFirstObject()
if not obj: return True
doc.StartUndo()
olist = []
while obj:
bb = obj.GetRad()
vol = int( (bb.x + bb.y + bb.z) / 3.0)
print vol
olist.append([vol,obj])
obj = obj.GetNext()
olist.sort()
olist.reverse()
for i,o in enumerate(olist):
doc.AddUndo(c4d.UNDOTYPE_CHANGE,o[1])
o[1].Remove()
doc.InsertObject(o[1],None,None)
c4d.EventAdd()
doc.EndUndo()
if __name__=='__main__':
main()
Dernière modification par Floc ; 31/10/2018 à 20h28.
Excellent merci beaucoup Floc !
Je tricotait au bon endroit mais je suis complètement largué en terme de syntaxe.
Effectivement à optimiser peut être en mettant une restriction, mais là tout de suite ça fait le taf pour ce que je dois faire. Et de là je devrai arriver avec cette base à adapter à d'autres paramètres.
Je posterai ça, si j'y arrive !
Merci encore
J'ai réussi à adapter le code comme je voulais (en revanche, pour restreindre ça à une sélection ou un groupe d'objet c'est au dessus de mes moyens !)
C'est surement pas le genre de truc qu'on utilise à tour de bras, mais dans certains cas particuliers ça peut être utile. Je met ça ici, si ça peut servir...
Pour trier les objets du gestionnaire en fonction de leur "taille" (bounding box), du plus petit au plus grand (j'ai rajouté la prise en compte de l'échelle de l'objet, car en sortie de mograph les objets modifiés par les effecteurs n'ont pas réellement changé de taille mais d'échelle)
Et pour trier les objets en fonction de leur distance avec la caméra active, du plus proche au plus éloigné (vue de l'éditeur si pas de camera objet)Code:# SORT OM OBJECTS : SIZE import c4d from c4d import gui def main(): obj = doc.GetFirstObject() if not obj: return True doc.StartUndo() olist = [] while obj: bb = obj.GetRad() scale = obj.GetAbsScale() vol = int( bb.x * bb.y * bb.z * scale.x * scale.y * scale.z ) print vol olist.append([vol,obj]) obj = obj.GetNext() olist.sort() olist.reverse() for i,o in enumerate(olist): doc.AddUndo(c4d.UNDOTYPE_CHANGE,o[1]) o[1].Remove() doc.InsertObject(o[1],None,None) c4d.EventAdd() doc.EndUndo() if __name__=='__main__': main()
Merci encore à Floc pour le coup de mainCode:# SORT OM OBJECTS : DISTANCE FROM ACTIVE CAMERA import c4d from c4d import gui def main(): obj = doc.GetFirstObject() bd = doc.GetRenderBaseDraw() cp = bd.GetSceneCamera(doc) if cp is None: cp = bd.GetEditorCamera() if not obj: return True doc.StartUndo() olist = [] while obj: pos1 = obj.GetMg().off pos2 = cp.GetMg().off dist = (pos2-pos1).GetLength() print dist olist.append([dist,obj]) obj = obj.GetNext() olist.sort() olist.reverse() for i,o in enumerate(olist): doc.AddUndo(c4d.UNDOTYPE_CHANGE,o[1]) o[1].Remove() doc.InsertObject(o[1],None,None) c4d.EventAdd() doc.EndUndo() if __name__=='__main__': main()
Dernière modification par Helium ; 01/11/2018 à 17h02.
Salut,
J'arrive un peu tard mais voilà comment faire un code un peu plus propre pour ceux que ça intéresse :
Ce code classe par ordre alphabétique les objets sélectionnés (ou tous si rien n'est sélectionné).Code PHP:
import c4d
def sort_objects(doc, sort_key, asc=True):
doc.StartUndo()
# Get objects
objects = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_0)
if not objects:
objects = doc.GetObjects()
# Sort objects
objects.sort(key=sort_key, reverse=asc)
# Remove and re-insert objects
for obj in objects:
doc.AddUndo(c4d.UNDO_OBJECT_DEL, obj)
obj.Remove()
doc.InsertObject(obj)
doc.AddUndo(c4d.UNDO_OBJECT_NEW, obj)
doc.EndUndo()
def main():
# Sort by name
sort_objects(doc, c4d.BaseObject.GetName)
c4d.EventAdd()
if __name__=='__main__':
main()
L'avantage c'est que pour ajouter des nouvelles méthodes de tri, y'a pas besoin de modifier ce qui a déjà été écrit mais simplement de créer une fonction qui retourne une valeur pertinente suivant ce que l'on veut faire :
Le code complet :Code PHP:
import c4d
def sort_objects(doc, sort_key, asc=True):
[...]
def get_bounding_box(obj):
bb = obj.GetRad()
scale = obj.GetAbsScale()
return int(bb.x * bb.y * bb.z * scale.x * scale.y * scale.z)
def main():
sort_objects(doc, get_bounding_box)
c4d.EventAdd()
L'utilisation d'une fonction lambda est nécessaire pour la distance avec la caméra parce que la fonction de tri doit prendre uniquement un élément du tableau en paramètre. Ça permet aussi de récupérer la caméra avant pour ne pas avoir à le faire pour chaque objet.Code PHP:
import c4d
def sort_objects(doc, sort_key, asc=True):
doc.StartUndo()
# Get objects
objects = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_0)
if not objects:
objects = doc.GetObjects()
# Sort objects
objects.sort(key=sort_key, reverse=asc)
# Remove and re-insert objects
for obj in objects:
doc.AddUndo(c4d.UNDO_OBJECT_DEL, obj)
obj.Remove()
doc.InsertObject(obj)
doc.AddUndo(c4d.UNDO_OBJECT_NEW, obj)
doc.EndUndo()
def get_active_camera(doc):
bd = doc.GetRenderBaseDraw()
cp = bd.GetSceneCamera(doc)
return bd.GetEditorCamera() if cp is None else cp
def get_distance_from_cam(obj, cam):
pos1 = obj.GetMg().off
pos2 = cam.GetMg().off
return (pos2 - pos1).GetLength()
def get_bounding_box(obj):
bb = obj.GetRad()
scale = obj.GetAbsScale()
return int(bb.x * bb.y * bb.z * scale.x * scale.y * scale.z)
def main():
# Sort by name
sort_objects(doc, c4d.BaseObject.GetName)
# Sort by bounding box
sort_objects(doc, get_bounding_box)
# Sort by distance from camera
camera = get_active_camera(doc)
sort_objects(doc, lambda obj: get_distance_from_cam(obj, camera))
c4d.EventAdd()
if __name__=='__main__':
main()
Salut,
Merci pour ces précisions ! Plus pratique en effet !
Bravo et merci pour ce script MAIS.....
Comment faire pour intégrer ce script a mon projet et classer mes objets
Merci pour votre aide
https://frenchcinema4d.fr/showthread...e-alphabetique
C4d r17_VrayforC4d_2 xeons X5650_24 Go RAM_EVGA SR2_Gtx 560TI