Hello
voir du code sur c4d m’a rendu un peu nostalgique... ça m’a rappelé la bonne époque où je m’éclater avec du basic sur mon vieux pc
Je partagerai donc, ici, les rares scripts que j’écrirai…. vu que je ne suis pas du tout un programmeur
Script I : Basic Test Scene
Script II: pour mes tests de rendu j’utilise souvent la forme ci-dessous, donc j'ai voulu automatisé un peu sa création...et surtout apprendre à créer une petite interface graphique
Code:import c4d from c4d import gui, documents class automatik(gui.GeDialog): btnID = 111 def CreateLayout(self): self.GroupBegin(999,c4d.BFH_CENTER,2,0,"paramètre :"); self.GroupBorder(c4d.BORDER_GROUP_IN) self.GroupBorderSpace(10,5,10,5) self.SetTitle("automatik") self.AddStaticText(0, c4d.BFV_CENTER, 0, 0, "Hauteur ", c4d.BORDER_NONE) self.AddEditText(3,c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT,200,10) self.AddStaticText(1,c4d.BFV_CENTER, 0, 0, "Profondeur", c4d.BORDER_NONE) self.AddEditText(4, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT,200,10) self.AddStaticText(2, c4d.BFV_CENTER, 0, 0, "Largeur", c4d.BORDER_NONE) self.AddEditText(5, c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT,200,10) self.GroupEnd() self.AddButton(self.btnID,c4d.BFH_SCALEFIT|c4d.BFV_SCALEFIT, 100, 15, "Valider") return True def Command(self, id, msg): if id == self.btnID: hauteur = 400+(100*(float(self.GetString(3)))) profondeur = 100*(float(self.GetString(4))) largeur = 100*(float(self.GetString(5))) Construction(hauteur, profondeur, largeur) self.Close() return True class Construction(): def __init__(self, htr, pfr, lgr): self.htr = htr self.pfr = pfr self.lgr = lgr #-------------------------- Mise en place : scene = documents.GetActiveDocument() # Creer spline sp = c4d.SplineObject(4,4) # Positions des points sp.SetPoint(0,c4d.Vector(0,0,pfr*-1)) sp.SetPoint(1,c4d.Vector(0,0,600)) sp.SetPoint(2,c4d.Vector(0,400,1000)) sp.SetPoint(3,c4d.Vector(0,htr,1000)) sp.Message(c4d.MSG_UPDATE) #Tangentes des pts sp.SetTangent(1,c4d.Vector(0,0,0),c4d.Vector(0,0,200)) sp.SetTangent(2,c4d.Vector(0,-200,0),c4d.Vector(0,0,0)) #Extrude objExt = c4d.BaseObject(c4d.Oextrude) objExt.SetPhong(True,False,80) objExt.SetName("Extrude") objExt[c4d.EXTRUDEOBJECT_MOVE] = c4d.Vector(lgr,0,0) sp.SetAbsPos(c4d.Vector((-1*lgr/2),0,pfr-1000/2)) scene.InsertObject(objExt) scene.InsertObject(sp,objExt) print("Done!") #----------------------------------------- if __name__=='__main__': dlg = automatik() dlg.Open(0,c4d.DLG_TYPE_MODAL_RESIZEABLE,700,300, 200) c4d.EventAdd()
Super !
bon apparemment t'es pas un débutant et te rassure je ne suis pas programmeur non plus (enfin j'sais pas si ça te rassure !)
Quelques petites remarques :
- Pourquoi utiliser du texte éditable (.AddEditText()) alors que tu as besoin plutôt de nombre donc utilise directement AddEditNumber ou encore mieux avec le flèches AddEditNumberArrows , cela t'évitera en plus après de convertir les string en float.
- attention avec documents.GetActiveDocument(), surtout ailleurs que dans les scripts, utilise directement simplement doc qui est prêt à l'emploi. Tu peux avoir des problèmes dans les tags ou générateurs lors du rendu car vu qu'il fait une copie du document ce n'est pas forcément celui qui restera actif(je sais pas si je suis clair là !)
- pour ton exemple un générateur d'objet python(menu python) avec des données utilisateurs serait beaucoup plus adapté car tu pourrais ensuite modifier ton objet à la volée comme un objet paramétrique. Ensuite sinon tu peux carrément faire un véritable objet paramétrique sous forme de plugin.
Allez hop le corrigé de l'exercice générateur d'objet ( à n'ouvrir que quand tu auras réussi seul !)
Après tu peux améliorer, en créant un réglage pour le rayon de courbure du plan
generateur_ksaa.c4d
lol... ok je vais essayer de le faire
Au fait comment on fait pour avoir accès à des variables qui sont dans d'autre fonctions ou class ?
pour ce qui est de (.AddEditText()), j'avais commencé par utilisé AddEditNumber, mais si je me souviens bien je ne pouvais entrer que des valeurs comprises entre 0 et 100.
merci oli_d
le P. generator c'est une autre histoire c'est exactement ce que je voulais faire au début, car dans mon premier code je ne pouvais plus modifier l'objet une fois créé.
là, j'ai viré l'interface graphique et je l'ai remplacé par l'UserData ( la moitié du code est déjà partie)... et j'ai même rajouter un scale pour faire varier la taille de l'objet... j'espère que le code est bon cette fois
Maintenant, une question un peu bête... comment faire pour l'utiliser lol? Avec le script manager je pouvais enregistrer le script, le placer dans un bouton dans l’interface de c4d, mais avec le générateur.... ?
Je pense que c’est le moment de voir la correction hein
un petit aperçu :
code:
Code:import c4d from c4d import gui, documents sp = c4d.SplineObject(4,4) objExt = c4d.BaseObject(c4d.Oextrude) doc.InsertObject(objExt) doc.InsertObject(sp,objExt) def main(): echelle = op[c4d.ID_USERDATA,6] hauteur = 400+(100*op[c4d.ID_USERDATA,2]) profondeur = 100*op[c4d.ID_USERDATA,3] largeur = 100*op[c4d.ID_USERDATA, 4] #-------------------------- Mise en place : # Positions des points sp.SetPoint(0,c4d.Vector(0,0,profondeur*-1)) sp.SetPoint(1,c4d.Vector(0,0,600)) sp.SetPoint(2,c4d.Vector(0,400,1000)) sp.SetPoint(3,c4d.Vector(0,hauteur,1000)) sp.Message(c4d.MSG_UPDATE) #Tangentes des pts sp.SetTangent(1,c4d.Vector(0,0,0),c4d.Vector(0,0,200)) sp.SetTangent(2,c4d.Vector(0,-200,0),c4d.Vector(0,0,0)) #Extrude objExt.SetPhong(True,False,80) objExt.SetName("Extrude") objExt[c4d.EXTRUDEOBJECT_MOVE] = c4d.Vector(largeur,0,0) sp.SetAbsPos(c4d.Vector((-1*largeur/2),0,profondeur-1000/2)) objExt.SetAbsScale(c4d.Vector(echelle)) c4d.EventAdd() print ("done!")
Dernière modification par ksaa ; 16/05/2011 à 18h50.
Super, je sens en toi un futur redoutable plugineur !
Dans le générateur la fonction main doit retourner un objet c4d qui peut évidemment avoir des enfants. Donc dans ton cas renvoie ton objExt dans lequel tu aura mis ta spline avec sp.InsertUnder(objExt) (tout est dans le corrigé).
Hors des scripts évite comme la mort les c4d.EventAdd, car tu risques de déclencher des boucles infinies, tu provoques un évènement qui relance le code qui provoque un évènement qui relance le code qui....
L'inconvénient des générateurs c'est que l'on ne peut pas les garder dans l'interface comme un plugin ou un script, il faut les copier/coller ou alors les mettre sous forme de fichier dans la médiathèque.
Donc pour faire ce que tu veux il faut faire un plugin et là ça se complique un peu. Je ne sais pas si tu as les exemples de plugins de Maxon, je me permets de les mettre en annexe au cas où (mettre les sous-dossier dans le dossier plugin de l'appli et redémarrer c4d). Regarde du côté du plug Py-RoundedTube et dans la doc dans le module c4d.plugins, surtout du côté de ObjectData
plugins.zip
en fait je t'ai dit que l'on ne pouvait pas stocker un générateur, mais on peut faire un script qui génère un générateur !
Dans la première partie on génère les UserData.
Ensuite le code n'est pas forcément très lisible, car on envoie le code du générateur dans le champ relatif.
C'était pour la beauté du geste, mais le plugin reste quand même plus logique ...
Code PHP:
import c4d
def AddRealData(obj,nom="UD"):
if obj is None: return
bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_REAL) #create default container
bc[c4d.DESC_NAME] = nom #rename the entry
bc[c4d.DESC_UNIT]=c4d.DESC_UNIT_METER # en metre
bc[c4d.DESC_MIN]=0 #limite minimum
element = obj.AddUserData(bc) #add userdata container
obj[element] = 300 #assign a value
def main():
doc.StartUndo()
obj = c4d.BaseObject(1023866)#objet python
AddRealData(obj,nom="hauteur")
AddRealData(obj,nom="profondeur")
AddRealData(obj,nom="largeur")
obj[c4d.OPYTHON_CODE]="""import c4d
def spline_ksaa(haut, prof, larg):
sp = c4d.SplineObject(4,c4d.SPLINETYPE_BEZIER)
sp.SetPoint(0,c4d.Vector(0,0,prof*-1))
sp.SetPoint(1,c4d.Vector(0,0,600))
sp.SetPoint(2,c4d.Vector(0,400,1000))
sp.SetPoint(3,c4d.Vector(0,haut,1000))
sp.SetTangent(1,c4d.Vector(0,0,0),c4d.Vector(0,0,200))
sp.SetTangent(2,c4d.Vector(0,-200,0),c4d.Vector(0,0,0))
sp.Message(c4d.MSG_UPDATE)
objExt = c4d.BaseObject(c4d.Oextrude)
objExt.SetPhong(True,False,80)
objExt.SetName("Extrude")
objExt[c4d.EXTRUDEOBJECT_MOVE] = c4d.Vector(larg,0,0)
sp.SetAbsPos(c4d.Vector((-1*larg/2),0,prof-1000/2))
sp.InsertUnder(objExt)
return objExt
def main():
haut = op[c4d.ID_USERDATA,1]
prof = op[c4d.ID_USERDATA,2]
larg = op[c4d.ID_USERDATA,3]
return spline_ksaa(haut, prof, larg)"""
obj.SetName("GeneKsaa")
doc.InsertObject(obj)
doc.AddUndo(c4d.UNDOTYPE_NEW, obj)
doc.SetActiveObject(obj)
doc.EndUndo()
c4d.EventAdd()
if __name__=='__main__':
main()
Super!
je vais essayer de décortiquer un peu le code
Merci pour ton investissement personnel dans ce que je fais
j'ai regardé aussi un peu pour faire un plugin et il y a quelques trucs qui m’échappent genre :
quésako ?Code:# be sure to use a unique ID obtained from www.plugincafe.com PLUGIN_ID = 1025250
L’exemple Py-RoundedTube est effectivement très intéressant, d'abord le dossier du plugin :
- un fichier Py-RoundedTube.pyp : c'est juste un fichier .py renommé en. pyp ou le résultat d'une manip?
- un dossier "res" :
---> un tif ( ok)
---> un fichier c4d_symbols.h (?)
---> un fichier .str (semble contenir des noms de variables et le texte affiché => remplace l'UD ?)
---> un autre fichier .h (?) (l’id de chaque composantes ??)
---> et un fichier .res (contient des informations : valeur min, max, etc...)
Je pars du principe que python est un langage interprété et non compilé, donc à quel moment ces fichiers ont été généré ?
Merci.
Allez, je vais tenter une réponse mais on risque de me corriger par la suite, voir de me taper sur les doigts.
Les différents plugin de C4D doivent tous avoir une ID unique.
Si deux plugin ont la même ID le risque c'est que des variables possédant le même nom soient utilisées malencontreusement dans le mauvais plugin.
Donc à la base, l'attribution d'un numéro ID unique pour chaque plugin permet d'éviter cette interaction.
Dans le temps l'attribution d'un numéro se faisait via le site plugincafe.com mais je ne sais pas si c'est toujours d'actualité.
Tu peux toujours rentrer un numéro au hasard pour tes tests il y a peu de chance que tu ais un problème.
Pour le reste je ne connais que les plugin coffee donc je ne peux pas vraiment t'aider.
En coffee on pouvait tout faire tenir dans un seul fichier .cof mais il était vivement conseillé pour la modularité de séparer ça dans plusieurs fichiers contenu dans le dossier res (ressources).
En particulier un fichier .str aussi il me semble, pour tout ce qui est texte. Et qui permettait par exemple de pouvoir facilement changer la langue du plugin. Sans rechercher au milieu du code toutes les parties textes.
De même pour les variables les plus importantes.
Les fichiers .cof n'étaient pas compilés non plus, donc on créait soit même ces fichiers.
SMC fan.
Merci Jean-Laurent
J’ai suivi ton conseil >> un nombre au hasard, et hop plus de message d’erreur
J’ai pu enfin, faire de ce petit bout de code un plugin détectable par c4d ! j’ai passé la quasi-totalité de mon temps à lire la doc, mais j’avoue que la plupart du temps elle me laisse sur ma faim… beaucoup de questions et peu de réponses, et les exemples sont très rares,… peut être que je l’exploite mal… maybe…
Voilà ou j’en suis pour le moment, le code génère bien un objet, Mais sans possibilité de modification et c’est là où je bloque…
Code:import c4d import os from c4d import plugins # be sure to use a unique ID obtained from www.plugincafe.com PLUGIN_ID = 1020684681 class Lobj(plugins.CommandData): def Execute(self, doc): sp = c4d.SplineObject(4,4) objExt = c4d.BaseObject(c4d.Oextrude) #--------------------------- UserData ----- doc.InsertObject(objExt) doc.SetActiveObject(objExt) noms = ["Hauteur","Profondeur","Largeur","Arrondi","Echelle"] valeurs = [5,3,15,100,1] for comp, val in zip(noms, valeurs): bc = c4d.GetCustomDatatypeDefault(c4d.DTYPE_REAL) #create default container bc[c4d.DESC_NAME] = comp #rename the entry UD = objExt.AddUserData(bc) #add userdata and set to container objExt[UD] = val hauteur = 400+(100*objExt[c4d.ID_USERDATA,1]) profondeur = 100*objExt[c4d.ID_USERDATA,2] largeur = 100*objExt[c4d.ID_USERDATA, 3] arrondi = objExt[c4d.ID_USERDATA,4] echelle = objExt[c4d.ID_USERDATA,5] #-------------------------- Mise en place : # Positions des points sp.SetPoint(0,c4d.Vector(0,0,profondeur*-1)) sp.SetPoint(1,c4d.Vector(0,0,(1000-arrondi*2))) sp.SetPoint(2,c4d.Vector(0,arrondi*2,1000)) sp.SetPoint(3,c4d.Vector(0,hauteur,1000)) sp.Message(c4d.MSG_UPDATE) #Tangentes des pts sp.SetTangent(1,c4d.Vector(0),c4d.Vector(0,0,arrondi)) sp.SetTangent(2,c4d.Vector(0,-arrondi,0),c4d.Vector(0)) #Arrondi #Extrude objExt.SetPhong(True,False,80) objExt.SetName("Extrude") objExt[c4d.EXTRUDEOBJECT_MOVE] = c4d.Vector(largeur,0,0) sp.SetAbsPos(c4d.Vector((-1*largeur/2),0,profondeur-1000/2)) objExt.SetAbsScale(c4d.Vector(echelle)) sp.InsertUnder(objExt) c4d.EventAdd() print ("done!") return True if __name__ == "__main__": icon = c4d.bitmaps.BaseBitmap() icon.InitWith(os.path.join(os.path.dirname(__file__), "res", "obj.tif")) c4d.plugins.RegisterCommandPlugin(PLUGIN_ID, "L-Object", 0, icon, "Generateur de L - Object", Lobj())
"Plugin IDs 1000001-1000010 are reserved for development. You may use these freely to test scripts, but must request an ID in order to release them."
Donc les ID de tests existent déjà. Il ne faut absolument pas prendre un chiffre au hasard. En cas de conflit, c'est l'utilisateur qui sera incapable de savoir pourquoi il y a un soucis.
Prendre un ID ça se fait sur le site de maxon, http://www.plugincafe.com/forum/developer.asp
Il faut s'enregistrer, donner un nom (ou pas) et cliquer. C'est immédiat et gratuit.
Pour l'aide ou les exemples, il y a http://www.plugincafe.com/forum/default.asp
Y a vraiment pas tout (et de loin) mais on trouve toujours un bout de code pour se prendre la tête dessus avant de trouver.
edit après zieutage du code :
Pour ce qui est de ton code, il n'est exécuté qu'une seule fois. C'est pour ça que la modification des DU ne change rien à ton extrusion. (si c'est ce que tu veux faire)
Si tu veux faire ce genre de chose, il faut passer par la création d'un objet générateur ou par un tag. Ces objets sont présents dans l'interface de c4d et sont "recalculé" à chaque frame ou suivant les messages de mises à jours de l'interface (touche A, mouvement de la souris, clic, modif d'un autre plugin etc etc)
Tu pourrais rajouter un tag python qui prendrait les DU pour mettre à jour le reste. (spline, extrusion). (qui devrait être le plus facile mais le plus bancale)
Si tu veux plonger un peu plus dans le développement, essayes de reconstruire l'objet extrusion directement. (faudra construire les poly, les UVs, gérer le niveau de subdivision)
Si tu veux juste faire un peu plus propre, tu peux créer un générateur d'objet, mettre ton extrusion et ta spline dedans caché et gérer la modifications via des DU.
Dernière modification par valkaari ; 17/05/2011 à 00h07.
Je savais bien qu'on allait me taper sur les doigts.
Je me souviens bien des ID test mais le problème c'est qu'avec 10 ID on en a vite fait le tour, surtout lorsqu'on est en phase d'apprentissage et qu'on test tout un tas de choses. Les plugin exemples utilisent ces mêmes ID d'ailleurs si ma mémoire est bonne ce qui en interdit déjà certaines.
Par contre pour le plugin définitif c'est autre chose. C'est bien pourquoi je parle de "tests".
A moins d'avoir 1000 plugin installés sur sa machine les chances d'avoir un plugin en conflit durant la phase de test en rentrant une ID de l'ordre du million sont quand même faibles.
L'erreur de programmation est hélas bien plus fréquente. (surtout pour moi )
SMC fan.
merci valkaari !!
Et voilà ! J’ai enfin ressui à créer un plugin ... le tout premier ... Ce fut long...surtout pour un si petit code, mais au moins j’ai pu apprendre quelques nouveaux trucs
ha... la mod me manque maintenant !
je mets le plug aussi, ça peut être utile pour les débutants comme moi
Dernière modification par ksaa ; 18/05/2011 à 17h37.
cool, tu peux aussi ajouter un bend dedans pour courber en plus le plan. enfin un neutre, le bend, l'extrude avec la spline dedans.
(j'ai pas regardé le code)
Un grand bravo !
J'ai regardé le code (en vitesse) et j'ai rien à redire -> bonne maîtrise du python SDK (software developpment kit)
c'est mieux par les temps qui courent qu'une bonne, qui ne maîtrise pas le python de DSK (bon ok je ->)
Dernière modification par oli_d ; 19/05/2011 à 16h09.
Bonsoir, bonsoir…
Lol… pas mal le jeu de mots
Cette fois j’ai essayé de faire un script qui imite la fonction "isolation" qui est dans 3ds max, je la trouve très pratique, surtout dans des scènes surchargées ...
Bon le code est encore à améliorer vu que j’ai des difficultés avec la class selection
Utilisation :
- sélection d'un objet puis >> isoler
- modif de l'objet... ou pas
- désélectionner tout puis >> isoler
Code Bonus
Code:import foot print (" !!! LE LOSC CHAMPION !!! Banzai !! ")
Dernière modification par ksaa ; 22/05/2011 à 04h32.
re Bonsoir...
Quelques petites corrections dans le code de "Isoler" >> le dernier {que j'avais posté}, fonctionnait de façon partielle… dès que j'ouvrais un fichier .c4d dont l’emplacement est diffèrent que celui en cours >> IOError
Dernière modification par ksaa ; 23/05/2011 à 01h38.
Bon ben rien à redire, je sens que je vais bientôt te demander des conseils ....
Je suis encore loin… Je galère avec tout ce qui est sélection .... par exemple, je n’arrive pas à trouver une fonction pour sélectionner tous mes objets… ou encore, savoir le nombre d’objets dans la scène ...je peux surement passer par une boucle... mais est ce que y'a plus simple ?
Dernière modification par ksaa ; 23/05/2011 à 10h19.
pour sélectionner il faut utiliser BaseList2D.SetBit(c4d.BIT_ACTIVE) ou DelBit pour déselectionner ou ToggleBit pour inverser.
Les fonctions recursives sont pas faciles à comprendre mais pour ce genre de chose c'est redoutable, juste un exemple qui sélectionne tous les objets et qui les compte (variantes d'utilisation de cette fonction récursive ici)
Code PHP:
import c4d
def select_objs(obj,i=0):
"""fonction recursive pour sélectionner tous les objets et renvoie le nombre d'objets"""
while obj :
obj.SetBit(c4d.BIT_ACTIVE) #sélection de l'objet pour déséléctionner remplacer SetBit par DelBit
i+=1 #compteur d'objets
i+=select_objs(obj.GetDown())# recursion : la fonction s'appelle elle-meme
obj = obj.GetNext()
return i
if __name__=='__main__':
obj = doc.GetFirstObject()
if obj :
print select_objs(obj) #imprime le nombre d'objet dans la console et les sélectionne tous
c4d.EventAdd()
merci oli
Je partage un petit bout de code suite au post de oli :
Code PHP:
import c4d
def doOnHierarchy(start, func):
i = 0
while start:
func(start)
i += 1 + doOnHierarchy(start.GetDown(), func)
start = start.GetNext()
return i
def selectObject(op):
op.SetBit(c4d.BIT_ACTIVE)
def addPhongTag(op):
op.MakeTag(c4d.Tphong);
def changeName(op):
op.SetName(op.GetName() + " new");
if __name__=='__main__':
print doOnHierarchy(doc.GetFirstObject(), selectObject)
doOnHierarchy(doc.GetFirstObject(), addPhongTag)
doOnHierarchy(doc.GetFirstObject(), changeName) # J'ai appelé la fonction plusieures fois pour l'exemple
c4d.EventAdd()
En gros c'est une factorisation du code qui permet d'appliquer une fonction sur chaque objet de la hiérarchie.
Ca ne fonctionne peut-être pas pour tous les cas d'utilisations et ça peut surement être amélioré mais ça évite de surcharger et de répéter le code avec des boucles.
C'est effectivement beaucoup plus propre et pratique, merci xs_yann !
Génial!
je ne savais pas qu'on pouvait passer une fonction en argument... et encore moins l'appeler dans son propre corps !!
en fait je n'ai jamais essayé ... ça me donne des idées
Merci à vous deux... je pense avoir saisi le principe
C'est le principe des pointeurs sur fonctions en C/C++, en Python apparement les fonctions sont considérées comme des objets. D'après ce que j'ai vu il y a même moyen de simuler une variable statique de cette manière :
Code PHP:
def func():
print func.x
func.x += 1
func.x = 0
def main():
func()
func()
func()
Dernière modification par xs_yann ; 24/05/2011 à 21h55.
Merci Yann
Bientôt j’aurai un peu plus de temps libre pour revoir les bases de python.
Aujourd’hui aussi j'ai fait un petit plugin, je n’ai pas résisté …
En mod, Un mesh avec 0 triangle fait toujours plaisir. Ce petit plug permet de trouver tous les triangles et de les grouper dans une sélection, pour faciliter la correction.
Merci Ksaa, je viens de tester ça fonctionne bien, avec quelques petites bizarreries :
(au cas où ça aurait une incidence, je suis en R12 Studio sur Os X)
Lorsque je sélectionne le module, j'ai dans un premier temps la boîte de dialogue de la commande "optimiser" qui apparaît :
une fois validé, la fenêtre de zTriangle apparaît :
petite suggestion : mettre "zTriangle" au lieu de "CINEMA 4D Studio" dans l'intitulé.
Et pour finir, si je fais un commande+z (ou ctrl+z) pour annuler, au lieu de revenir à l'objet avant application du module, j'ai droit à toutes les étapes intermédiaires réalisées par le plug. (c'est un peu embêtant)
Je ne sais pas si tu peux ou as envie d'améliorer, c'est déjà bien utile en l'état, merci
÷ R19 Studio ÷ cacahuètes ÷
Merci Sir Gong
J’ai refait mon code en partie pour le rendre un peu plus " propre " :
- plus de boite " optimiser "
- Undo possible
- boites de dialogue plus adaptées
- Suppression des n-gons (résultat = quad + triangle)
Dernière modification par ksaa ; 23/06/2011 à 07h52.
Beaucoup mieux merci !
÷ R19 Studio ÷ cacahuètes ÷
Bonsoir mes amis!
Quelqu’un pourrait me faire un petit tuto pour une intro ? hum ... désolé… fallait que ça sorte
Plus sérieusement, question beaucoup plus simple, enfin, je l'espère,
en python, quelle est la signification du ~ (tilde), j’ai fait quelques recherches mais …
voici un petit exemple :
la console affiche -3 comme résultat, et la o_O! que quoi cmment ?Code:a = 2 b = ~a print b
Merci d'avance