Bonjour à tous.
Après avoir lu un tweet de Patrick Letourneau : https://twitter.com/PolygonSandwich/...37946457239553,
j'ai décidé de me coller à la programmation d'un script pour résoudre ce problème.
Voici donc ce qu'il est censé réaliser:
Pour chaque objet sélectionné :
- Effacer les doublons de tags de texture
- Effacer les tags de sélection vide
- Effacer les tags de texture restreint à des tag de sélection qui n'existe pas
C'est sûrement très mal programmé, je débute totalement en python, mais si vous avez l'occasion de le tester, je suis avide de retours...
Code:import c4d from c4d import gui ### For selected polygon objects ### - remove empty selection tags ### - remove texture tags restricted to non-existing selection tag ### def nettoie_polygon_tag(t,anciens_tags): """ on s'occupe des selections de polygones """ s = t.GetBaseSelect() if s.GetCount() == 0: t.Remove() def nettoie_texture_tag(t,anciens_tags): """ on s'occupe des textures """ flag_a_garder = False if t[c4d.TEXTURETAG_RESTRICTION]: la_restriction = t[c4d.TEXTURETAG_RESTRICTION] # verifie si restriction existe dans selectiontag for tt in anciens_tags: if type(tt) is c4d.SelectionTag: if tt.GetName() == str (la_restriction): flag_a_garder = True else: flag_a_garder = True if not flag_a_garder: t.Remove() def nettoie_doublon_texture_tag(tag,anciens_tags): """ on ne garde que la derniere texture """ tags_tex_liste = [] for tt in anciens_tags: if type(tt) is c4d.TextureTag: if not tt[c4d.TEXTURETAG_RESTRICTION]: tags_tex_liste.append(tt) ## tt.Remove() ## remet le dernier print tags_tex_liste print (len (tags_tex_liste) ) def nettoie_tags(o): """ Nettoyage des Tags """ ### Passe 1 : virer tag textures doublons anciens_tags = o.GetTags() for tag in anciens_tags: if type(tag) is c4d.TextureTag: tags_tex_liste = [] for tag in anciens_tags: if type(tag) is c4d.TextureTag: if not tag[c4d.TEXTURETAG_RESTRICTION]: tags_tex_liste.append(tag) tag.Remove() c4d.EventAdd() ## Passe 2 : remetre le dernier tag texture if len (tags_tex_liste) > 0: le_dernier_tag = tags_tex_liste[len(tags_tex_liste) - 1] print le_dernier_tag o.InsertTag(le_dernier_tag) c4d.EventAdd() ### Passe 3 : virer selection polygones vides anciens_tags = o.GetTags() for tag in anciens_tags: if type(tag) is c4d.SelectionTag: nettoie_polygon_tag(tag,anciens_tags) c4d.EventAdd() ### Passe 4 : virer tag textures dont la restriction n'existe pas anciens_tags = o.GetTags() for tag in anciens_tags: if type(tag) is c4d.TextureTag: nettoie_texture_tag(tag,anciens_tags) c4d.EventAdd() def main(): ledoc = c4d.documents.GetActiveDocument() ## type : c4d.documents.BaseDocument laselection = ledoc.GetActiveObjects(0) ## type : list ledoc.StartUndo() for ob in laselection: ## type: c4d.PolygonObject doc.AddUndo(c4d.UNDOTYPE_CHANGE,ob) nettoie_tags(ob) ledoc.EndUndo() c4d.EventAdd() if __name__=='__main__': main()
Salut et bienvenue !
Tout d'abord pour un premier script je trouve que tu t'en sors vraiment très bien. Plutôt que d'essayer de corriger tout ton code je te montre comment j'aurais abordé le problème, si tu ne comprends pas des trucs n'hésites pas à demander:
Explications dans l'ordre :Code PHP:
import c4d
def main():
doc.StartUndo()
for o in doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_0):
doc.AddUndo(c4d.UNDOTYPE_CHANGE,o)
#################################################
#suppression des tags de sélection de polygones vides
for t in o.GetTags():
if t.CheckType(c4d.Tpolygonselection):
bs = t.GetBaseSelect()
if not bs.GetCount(): t.Remove()
#liste des noms des tags de sélection qui restent par une ompréhension de liste
sel_names = [t.GetName() for t in o.GetTags() if t.CheckType(c4d.Tpolygonselection)]
#################################################
#suppression des tags texture avec restriction qui n'existent pas
for t in o.GetTags():
if t.CheckType(c4d.Ttexture):
restrict = t[c4d.TEXTURETAG_RESTRICTION]
if restrict and restrict not in sel_names: t.Remove()
#################################################
#suppression de tous les tags texture sans restriction sans le dernier
#liste de tous les tags texture qui n'ont pas de restriction
tags_tex = [t for t in o.GetTags() if t.CheckType(c4d.Ttexture) and not t[c4d.TEXTURETAG_RESTRICTION]]
#on supprime tout sauf le dernier
for t in tags_tex[:-1] : t.Remove()
doc.EndUndo()
c4d.EventAdd()
if __name__=='__main__':
main()
- hors plugin tu peux utiliser la variable doc pour remplacer c4d.documents.GetActiveDocument(), c'est plus court à écrire
- j'utilise souvent les compréhensions de liste, c'est vachement pratique en python
- dans une liste si tu veux le dernier élément tu peux écrire list[-1] si tu veux tous les éléments sauf le dernier list[:-1] (voir d'autres combines ici)
En ce qui concerne les fonctions, je suis toujours un peu partagé. Pour les scripts courts je préfére taper le code à la suite, je trouve ça plus lisible. Mon critère pour utiliser une classe ou une fonction, c'est dès que tu commences à copier/coller des portions de code c'est qu'il faut créer soit une classe soit une fonction. Pour les codes plus long, c'est une autre problématique.
Il y a évidemment toujours 40 manières d'arriver au même résultat. J'ai appris sur le tas et je fais sûrement des trucs pas très catholiques. Il y a des plus pro sur le forum, comme xsYann, Valkaari et César qui me corrigeront si j'ai dit des conneries.
En tous cas bravo, ça fait toujours plaisir de voir pointer des nouveaux codeurs par ici.
PS :Si il y a un modo qui passe, je vote pour qu'on le désensable et que l'on bouge ce sujet dans la section programmation
Dernière modification par oli_d ; 22/01/2016 à 20h51.
ouaip je fais ça !
kenavo !! // Pinterest KAMIGAZ®
ça c'est du rapide, merci Aurety !
Merci beaucoup Oli_d pour ta réponse super détaillée et Aurety pour ta promptitude.
Ca va me prendre un peu de temps de bien comprendre ton code, mais c'est super interessant d'avoir le corrigé !
Bon je vais déjà potasser :
- bin le python de base....
- les listes
- les compréhensions de liste, rien que le nom m'intrigue
Et merci pour les conseils.
j'avais complètement raté ce post tient.
tags_tex = [t for t in o.GetTags() if t.CheckType(c4d.Ttexture) and not t[c4d.TEXTURETAG_RESTRICTION]]
En plus d'être pratique c'est d'une élégance folle.
Bonjour,
Je suis sur c4d r20 et ça fait plus de 6 heures que je cherche désespérément à écrire un script python qui sélectionne tous tags de texture assignés aux objets de scène, puis qui change la valeur de restriction (TEXTURETAG_RESTRICTION) à "0".
Ca désactiverait toutes les textures, également dans le live viewport d'octane.
Pour le moment, je débute et ça m'a donc pris des lustres pour comprendre un peu le language et écrire cela :
Quand j’exécute, ça sélectionne tous tags de texture assignés aux objets de scène mais impossible de changer les valeurs de restriction sur tous en même temps.Code:import c4dfrom c4d import gui def main(): c4d.CallCommand(300001025) # Select All c4d.CallCommand(16370, 16370) # Select Texture Tags/Objects s = doc.GetActiveTags() for i in s: tag(i)[c4d.TEXTURETAG_RESTRICTION] = "off#" c4d.EventAdd() if __name__=='__main__': main()
Auriez-vous une solution ?
Merci d'avance !
Antoka
Dernière modification par Antoka ; 25/08/2019 à 11h33.
Salut,
Essaie ça plutôt :
Code:for i in s: i[c4d.TEXTURETAG_RESTRICTION] = "off#"
Ce serait plus joliment écrit comme ceci :
Code:tags = doc.GetActiveTags() for tag in tags: tag[c4d.TEXTURETAG_RESTRICTION] = "off#"
Dernière modification par César Vonc ; 25/08/2019 à 10h10.
Merci BEAUCOUP César Vonc.
J'étais pas si loin, merci encore. Le chemin va être long avant de maîtriser ce langage.
Aussi j'aurais une nouvelle question, je ne sais pas c'est approprier de la poser à la suite.
Je cherche à écrire un script qui sélectionne puis fusionne tous les shaders ayant le même "MATERIAL_COLOR_SHADER"
Pour l'instant j'ai ça qui me permet de fusionner les shaders sélectionnés manuellement :
Maintenant je n'ai aucune idée de ce que je pourrait écrire devant afin de ça trouve et sélectionne les doublons. Ce scripts me serait très utiles quand j'importe des persos en fbx issue de DAZ. Il y a toujours 1000 shaders dupliqué à fusionner ça prend du temps. Peut-être qu'un script existe déjà, mais je n'ai rien trouvé pour l'instant.Code:import c4d def main(): mats = doc.GetActiveMaterials() list_tags = list() for mat in mats: obj_link = mat[c4d.ID_MATERIALASSIGNMENTS] for i in xrange(obj_link.GetObjectCount()): list_tags.append(obj_link.ObjectFromIndex(doc, i)) doc.StartUndo() for tag in list_tags: doc.AddUndo(c4d.UNDOTYPE_CHANGE, tag) tag[c4d.TEXTURETAG_MATERIAL] = mats[0] for mat in mats[1:]: doc.AddUndo(c4d.UNDOTYPE_DELETE, mat) mat.Remove() doc.EndUndo() c4d.EventAdd() if __name__=='__main__': main()
Merci encore !
Antoka
Dernière modification par Antoka ; 25/08/2019 à 11h33.
Pour ça, il faut regrouper tes matériaux dans un dictionnaire avec comme clef le nom de la texture, par exemple :
Code PHP:
mats = doc.GetMaterials()
dico = {}
for mat in mats :
clef = 'vide'
tex = mat[c4d.MATERIAL_COLOR_SHADER]
if mat[c4d.MATERIAL_USE_COLOR] and tex and tex[c4d.BITMAPSHADER_FILENAME] : clef = tex[c4d.BITMAPSHADER_FILENAME]
if clef in dico :
dico[clef].append(mat)
else :
dico[clef] = [mat]
groupes = dico.values()
for mats in groupes :
print mats # Et là tu peux appeler ta fonction de dédoublonnage
Après, est-ce que la fonction de C4D ne ferait pas l'affaire ? Dans le gestionnaire de matériaux : Fonction > Supprimer les matériaux en double.