PDA

Voir la version complète : remplacer automatiquement les Path des xref et textures



phobos34
14/11/2012, 15h27
Salut,

voila je cherche a faire un petit script en python pour remplacer automatiquement tous les chemins (xref, texture...)
dans un fichier .c4d par un chemin vers un répertoire unique.(ou l'on stock toute nos data)

Vous avez une idée de la fonction qu'il faut utiliser pour cela ?

Merci

valkaari
14/11/2012, 15h56
je sais pas s'il y a une fonction pour changer tous les chemins dans les textures ou les objets. Par contre tu peux les parcourir tous avec une fonction récursive.

Pour ce qui est du changement du chemin il faut regarder du coté de os.path.split et os.path.join pour décomposer et recomposer un chemin.
l'idée c'est de récupérer le chemin existant, le décomposer pour ne garder que le fichier et non le chemin et recomposer avec le nouveau chemin.



edit : mouais bon la nouvelle xref de la R14 semble fonctionner différemment, même en activant l'option générateur j'arrives pas à changer le chemin hu hu hu.

phobos34
14/11/2012, 17h38
merci valkaari,

tu auras un exemple de code afin de voire la syntaxe (je début en prog sous c4d)
pour les xref de la version 14 avec une telle fonction ca ne sera plus un problème, on les ouvre un par un et on modifie leurs chemin interne via le script (comme on le fait dans 3ds max par exemple).

Merci

valkaari
14/11/2012, 18h38
pas bien compris ton histoire d'ouvrir les xref là xD

phobos34
14/11/2012, 20h59
tu ouvre chaque xref (fichier .c4d) seul, tu exécute le script et tu sauve, comme cela tous les chemins sont rediriger vers le nouveau
répertoire.

César Vonc
14/11/2012, 22h49
Voilà qui devrait déjà modifier l'emplacement de toutes les textures de tous les matériaux :


import os
import c4d

def ChangeLien(bitmap, mat) :
lien = bitmap[c4d.BITMAPSHADER_FILENAME]
lien = "mondossier\\" + os.path.basename(lien)
bitmap[c4d.BITMAPSHADER_FILENAME] = lien
mat.Message(c4d.MSG_UPDATE)

def main():
mats = doc.GetMaterials()
for mat in mats :
tex = mat.GetFirstShader()
while tex :
texs = [tex]
for t in texs :
if t.CheckType(c4d.Xbitmap) :
ChangeLien(t, mat)
texs.extend(t.GetChildren())
tex = tex.GetNext()

c4d.EventAdd()

if __name__=='__main__':
main()Ce n'était pas si évident, étant donné que la texture bitmap pouvait être dans une ou plusieurs autres matières, comme un calque ou une quelconque autre matière modificatrice. Il y a sûrement d'autres moyens de faire.


tex = mat.GetFirstShader() récupère la matière du premier canal du matériau.
tex = tex.GetNext() récupère la matière du canal actif suivant du matériau

texs est la liste des sous-matières, initialisée avec tex, puis étendue de ses sous-matières grâce à texs.extend(t.GetChildren()) tant qu'il y en aura.

Si la matière est de type c4d.Xbitmap, alors on change son lien via la fonction perso ChangeLien().


Ceci dit, je suis un piètre prof, donc si t'as des questions, n'hésite pas.

valkaari
15/11/2012, 00h29
ha ben si t'ouvres toutes tes xref ça devient plus simple ^^

sinon césar tu peux aussi demander la sélection du répertoire où sont stockés les bordels là


path = c4d.storage.LoadDialog(c4d.FILESELECTTYPE_ANYTHING ,"Selectionnez un répertoire",c4d.FILESELECT_DIRECTORY)

et après tu peux faire utiliser la commande
os.path.join (path, os.path.basename(lien) )

le chemin dépendra de l'os comme ça. (attention aux problèmes qui pourraient survenir dans un environnement hétérogène)

phobos34
15/11/2012, 09h45
Merci César !

Ta fonction marche vraiment au top, encore merci !

une dernière petite question (je sais j'abuse un peut), si je veux rajouter dans ta fonction la même opération (modifier un chemin)
mais pour les xref , pour modifier le chemin qui pointe vers l'xref source.
je doit utiliser qu'elle commande ? (je ne connais pas encore le language de c4d)

Dans c4d il n'y pas ne cache file ?(enfin d'autre éventuel fichiers externe a rediriger)
Comme cela le script permettra de rediriger tous les chemins des data (maping, xref...) vers un seul répertoire.

encore merci

César Vonc
15/11/2012, 11h16
Oui, c'est vrai qu'il est plus propre d'utiliser os.path.join().


Pour parcourir tous les objets du document à la recherche d'Xref, tu peux faire comme ceci :


import c4d

def main():
objets = doc.GetObjects()
for obj in objets :
if obj.CheckType(c4d.Oxref):
print obj
objets.extend(obj.GetChildren())

if __name__=='__main__':
main()

Pour récupérer et modifier l'attribut d'un objet, il suffit de le glisser dans la fenêtre Python.


Ceci dit, j'avoue que j'arrive pas non plus à modifier le chemin d'un Xref :

obj[c4d.ID_CA_XREF_FILE] = "nouveaufichier.c4d"

devrait pourtant fonctionner... bizarre.

phobos34
15/11/2012, 11h42
merci César,

je vais faire des tests avec ta fonction.

phobos34
15/11/2012, 12h22
la je suis un peut bloquer , je n'arive pas tracer les fonction via la fenêtre Python le nom de la fonction pour modifier le chemin (obj[c4d.ID_CA_XREF_FILE] se semble pas fonctionner sous la R13)
et celle de la fonction pour activer dans "xref/option" l'import du matériau afin de modifier les chemins dans celui-ci

César Vonc
18/11/2012, 17h54
Oui, la modification d'une option d'un Xref ne semble pas fonctionner en Python dans la R13.

J'ai essayé avec GetData() et SetData(), qui semble un peu moins mal marcher mais rendent le Xref instable avec une espèce de problème de rafraîchissement.


Pas vraiment de solutions, pour le coup...

phobos34
18/11/2012, 18h55
Merci César,

moi aussi j'ai fait pas mal de test mais en vin, ça craint un peut pour C4D, c'est quand même une fonction de base de pouvoir juste éditer un chemin (peut être pas encore super au point le python pour la R13)
tu as tester ta fonction en COFFEE ?
on peut appel du COFFEE depuis un script python ? (comme dans maya ou l'on peut appeler des fonctions mel depuis python)

encore merci

valkaari
18/11/2012, 19h59
C'est pas lié au language de prog mais à la modification du xref. Comme je l'ai dit un peu plus haut, certains disent que dans la r14 il faut passer le xref en mode générateur. (qui n'existe pas dans la/les versions précédentes)

Mais même comme ça, j'ai pas trouvé comment changer ce chemin.

Sinon oui, la prog sous c4d c'est vraiment à chier dans certains points. (voir beaucoup)

César Vonc
18/11/2012, 22h50
En effet, même en Xpresso, ça ne marche pas.


Ceci dit, si tu veux vraiment économiser les clics, tu peux appeler le bouton de sélection de fichier de chaque Xref en insérant cette ligne dans la boucle de recherche des objets Xref :


c4d.CallButton(obj, c4d.ID_CA_XREF_FILE_SELECT)C'est toujours mieux que rien et évite de rechercher manuellement les Xref dans le document.

phobos34
19/11/2012, 07h54
j'ai pas trop compris le principe, tu simule le clic sur le bouton ?
si oui via cette fonction on peut complétement l'automatiser via un pilotage de l'interface graphique ?

Mon script C4d doit être complétement autonome.

Dans 3dmax j'ai eu un peut le même problème, une fonction buger via le script, j'ai résolut le problème en utilisant cette fonction via l'interface graphique (non buger), mon script pilotent complétement l'interface graphique, au final ça marche super bien !

On peut peut être faire pareil pour C4D ?

merci

oli_d
19/11/2012, 08h58
Chez moi aussi je n'arrive pas à changer la reférence.

J'ai fouiné un peu dans oxref.h et en codant :

op[c4d.ID_CA_XREF_REF_STATEFILE] = "nouveaufichier.c4d"

cela vide le champ reférence mais si on fait
print op[c4d.ID_CA_XREF_FILE]

cela nous print bien le nouveau nom de fichier dans la console.
Par contre impossible de mettre à jour cet xref.... :icon_banghead:

César Vonc
21/11/2012, 10h03
j'ai pas trop compris le principe, tu simule le clic sur le bouton ?
si oui via cette fonction on peut complétement l'automatiser via un pilotage de l'interface graphique ?

Oui, CallButton appelle la fonction d'un bouton, comme lorsqu'on clique dessus.

Mais je ne pense pas qu'on puisse faire quelque chose de plus élaboré, le bouton en question ouvre une boîte de dialogue modale qu'on ne peut pas contrôler en Python, du moins à ma connaissance.



Sinon, il reste la solution du XML. Tu peux exporter ton document au format CINEMA 4D XML, l'ouvrir avec un éditeur de texte pour modifier les chemins des fichiers à l'aide d'une macro, par exemple, ou bien en Python avec la classe xml.dom.minidom.
Il ne te restera plus qu'à le réimporter dans C4D.

Mais bon, ce XML peut être très très volumineux, donc très lourd à manipuler.

phobos34
21/11/2012, 10h43
la solution du fichier xml ne me semble pas top, il faut chercher du coter de du pilotage de l'interface graphique.
On sait que la fonction marche parfaitement de cette façon, et cela peut servir pour d'autre fonction pas la suite, il n'y a plus de limitation (si on y arrive), ainsi on peut potentiellement utiliser n'importe quelle fonction via l'interface graphique de C4D.