Je propose de tenir un sujet de référencement des bogues en tout genre liés à la programmation Python, afin de ne pas submerger le sujet de référencement général de fragments de codes pas très explicites.
Le but est non seulement de référencer les problèmes connus afin d'éviter toute perte de temps, mais également proposer des solutions de secours.
S'il est également possible de rapporter ces coquilles pour une future correction, ce ne serait évidemment pas plus mal. ^^
--
Vector.__rxor__ : Opérateur erroné
BaseObject.CopyTagsTo : Description erronée
BaseDraw.GetEditorCamera : Argument erroné
ViewportSelect.GetPixelInfoPolygon : Exemple erroné
SendModelingCommand MCOMMAND_SPLIT : Description incomplète
SendModelingCommand MCOMMAND_JOIN : Fonction boguée
Offd : Taille boguée
GvPort.SetName(name) : Fonction boguée
GvNode.AddPort(c4d.GV_PORT_INPUT, c4d.GV_OBJECT_OPERATOR_OBJECT_IN) : Fonction boguée
GvNode.SetPortType(port, id) : Fonction boguée
--
R15.037 - Vector.__rxor__(self, other)
L'opérateur % entre deux vecteurs ne renvoie pas la multiplication entre chaque composant du vecteur mais le produit vectoriel.
Solution :Code PHP:
v = c4d.Vector(1,2,3) % c4d.Vector(2,3,4) # Vector(-1, 2, -1)
Code PHP:
v = c4d.Vector(1,2,3).__rxor__(c4d.Vector(2,3,4)) # Vector(2, 6, 12)
--
R15.037 - BaseObject.CopyTagsTo(dest, visible, variable, hierarchial)
Description erronée :
Set the ip of the object.
--
R15.037 - BaseDraw.GetEditorCamera(doc)
Retourne une erreur à cause de l'argument doc.
Solution :Code PHP:
bd = doc.GetActiveBaseDraw()
camera = bd.GetEditorCamera(doc) # TypeError: GetEditorCamera() takes no arguments (1 given)
Code PHP:
bd = doc.GetActiveBaseDraw()
camera = bd.GetEditorCamera()
--
R15.037 - ViewportSelect.GetPixelInfoPolygon(x, y)
L'exemple utilise GetPixelInfoPoint au lieu de GetPixelInfoPolygon.
infopoint = viewportselect.GetPixelInfoPoint(x, y)
--
R15.037 - c4d.utils.SendModelingCommand(command, list[, mode=MODIFY_ALL[, bc[, doc[, flags]]]]) - MCOMMAND_SPLIT
Manque de précision : la commande MCOMMAND_SPLIT renvoie une liste d'objets.
--
R15.037 - c4d.utils.SendModelingCommand(command, list[, mode=MODIFY_ALL[, bc[, doc[, flags]]]]) - MCOMMAND_JOIN
La commande MCOMMAND_JOIN unit tous les objets de la même hiérarchie se trouvant après le premier objet de la liste.
Les coordonnées du nouvel objet obtenu sont les mêmes que celles du premier objet de la liste, alors que pour correspondre aux anciens objets, ces coordonnées doivent être nulles.
Solution :Code PHP:
# Créez au préalable trois objets éditables
op = doc.GetFirstObject()
op2 = op.GetNext()
ops = [op, op2]
res = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_JOIN,
list = ops,
doc = doc)
if res : doc.InsertObject(res[0]) # Les trois objets sont unis et décalés
c4d.EventAdd()
Créer virtuellement un objet neutre dans lequel placer les objets à unir.
Code PHP:
# Créez au préalable trois objets éditables
op = doc.GetFirstObject()
op2 = op.GetNext()
ops = [op, op2]
neutre = c4d.BaseObject(c4d.Onull)
for obj in ops : obj.GetClone().InsertUnder(neutre)
res = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_JOIN,
list = [neutre],
doc = doc)
if res : doc.InsertObject(res[0]) # Les deux objets sont unis et correctement positionnés
c4d.EventAdd()
--
R15.037 - Offd (Déformation libre)
Impossible de définir la taille de la grille, bien que le champ soit modifiable.
Solution :Code PHP:
obj = c4d.BaseObject(c4d.Offd)
obj[c4d.FFDOBJECT_SIZE] = c4d.Vector(10.0) # Valeur modifiée, mais visuellement à sa valeur par défaut (300).
doc.InsertObject(obj)
c4d.EventAdd()
Proposée par xs_yann : Mettre à jour manuellement la propriété c4d.Tpoint.
Dernière modification par César Vonc ; 08/10/2014 à 21h33.
Salut,
Très bonne idée ce topic César.
Pour le FFD j'avais posté la solution sur plugincafe.
En fait c'est le PointTag qui n'est pas mis à jour correctement.
Il faut donc :
1. Récupérer le PointTag
2. Récupérer les positions des points dans le PointTag
3. Multiplier toutes les positions par un facteur taille.
4. Mettre la taille correspondante dans les paramètres du FFD
Code PHP:
import c4d
def setFFDSize(ffd, size):
tag = ffd.GetTag(c4d.Tpoint) # 1
points = tag.GetAllHighlevelData() # 2
oldSize = ffd[c4d.FFDOBJECT_SIZE]
scaleFactor = c4d.Vector(size.x / oldSize.x, size.y / oldSize.y, size.z / oldSize.z)
for i, point in enumerate(points):
points[i].x *= scaleFactor.x # 3
points[i].y *= scaleFactor.y
points[i].z *= scaleFactor.z
tag.SetAllHighlevelData(points)
ffd[c4d.FFDOBJECT_SIZE] = size # 4
ffd.Message(c4d.MSG_UPDATE)
def main():
setFFDSize(doc.GetActiveObject(), c4d.Vector(1200, 350, 100))
c4d.EventAdd()
if __name__=='__main__':
main()
Oh, merci Yann, c'est parfait, fallait le trouver !
J'ajoute un lien vers ton message en solution.
Nouvelle prise de tête qui m'a coûté une soirée, encore avec SendModelingCommand, j'ignore si c'est un bogue ou juste un truc à savoir, mais si vous utilisez la commande MCOMMAND_MAKEEDITABLE, votre objet doit se trouver dans le document avant puis être réinséré après.
Ce qui est contraire, par exemple, à la commande MCOMMAND_CURRENTSTATETOOBJECT qui ne nécessite pas d'avoir l'objet dans le doc pour son exécution.
Code PHP:
import c4d
def main():
obj = c4d.BaseObject(c4d.Osplinecircle)
doc.InsertObject(obj) # Indispensable
ret = c4d.utils.SendModelingCommand(
command=c4d.MCOMMAND_MAKEEDITABLE, list=[obj], doc=doc)
if ret : doc.InsertObject(ret[0])
c4d.EventAdd()
if __name__=='__main__':
main()
d'après la doc
Donc c'est un fonctionnement "prévu"The document for the operation. Should be set if possible. Must be set for MCOMMAND_MAKEEDITABLE, MCOMMAND_CURRENTSTATETOOBJECT and MCOMMAND_SPLINE_PROJECT.
A la rigueur c'est le currestate qui ne fonctionne pas comme prévu si tu ne spécifie pas le document.
Par contre il y a des commandes qui nécessitent de réinsérer l'objet dans le document et d'autre non. Insérer un objet dans un document ça prend du temps, donc c'est pas forcement un mal qu'il ne le fasse pas à tous les coups.
Le problème, et je te rejoins dans ta remarque, c'est que toutes les fonctions n'ont pas le même comportement, et parfois c'est une perte de temps et une prise de tête très importante.
R15.008 - GvPort.SetName(name)
GvPort.SetName(name) modifie le nom du noeud parent (GvNode) au lieu de celui du port.
Code PHP:
xpresso = c4d.BaseTag(c4d.Texpresso)
op.InsertTag(xpresso)
master = xpresso.GetNodeMaster()
python_node = master.CreateNode(master.GetRoot(), ID_OPERATOR_PYTHON)
python_node.RemoveUnusedPorts()
port = python_node.AddPort(c4d.GV_PORT_OUTPUT, c4d.OUT_STRING)
port.SetName("Foobar")
--
R15.008 - GvNode.AddPort(c4d.GV_PORT_INPUT, c4d.GV_OBJECT_OPERATOR_OBJECT_IN)
Impossible d'ajouter un port objet sur un noeud objet (ni en entrée, ni en sortie).
Solution :Code PHP:
object_node = master.CreateNode(master.GetRoot(), c4d.ID_OPERATOR_OBJECT)
object_node[c4d.GV_OBJECT_OBJECT_ID] = op
object_node.AddPort(c4d.GV_PORT_INPUT, c4d.GV_OBJECT_OPERATOR_OBJECT_IN)
Proposée sur plugincafe : Créer une donnée utilisateur de type lien vers l'objet. Ce n'est pas très élégant mais ça fonctionne.
Code PHP:
bc = c4d.GetCustomDataTypeDefault(c4d.DTYPE_BASELISTLINK)
bc[c4d.DESC_NAME] = "Object"
bc[c4d.DESC_SHORT_NAME] = "Object"
bc[c4d.DESC_DEFAULT] = op
ud = op.AddUserData(bc)
op[ud] = op
object_node.AddPort(c4d.GV_PORT_INPUT, ud)
--
R15.008 - GvNode.SetPortType(port, id)
GvNode.SetPortType(port, id) ne change pas le type du port.
Solution :
Faire un appel à GvNode.AddPort avant avec le même type.
Code PHP:
python_node.AddPort(c4d.GV_PORT_OUTPUT, c4d.OUT_STRING)
output_port = python_node.GetOutPort(0)
python_node.SetPortType(output_port, c4d.OUT_STRING)
Dernière modification par xs_yann ; 02/10/2014 à 15h46.
Merci pour le partage, Yann !
J'ai mis à jour le premier message du sujet.
Je vous admire les gars !
La moindre ligne de code me fait fuir. Une ligne de basse ok, mais une ligne de code, c'est de la torture pour moi.
Quant à la ligne de coke, ça m'a jamais tenté.
Tout ce que j'écris est à prendre au 15e degré. Car comme dit le proverbe chinois : Quand le dragon d'or, le ragondin ; voilà qui devrait faire taire les critiques et me mettre à l'abri d'attaques frontales.
La classe Vector a une curieuse façon d'arrondir les float :
qui me donne dans la console :Code PHP:
import c4d
def main():
v = c4d.Vector(1094854.6949,1094854.6949,1094854.6949)
print v
print v.x
print v.y
print v.z
if __name__=='__main__':
main()
Vector(1094854.695, 1094854.75, 1094854.75)
1094854.6949
1094854.75
1094854.75
En x tout se passe bien, par contre en y et z, il arrondi de façon bizarre.
Vous me direz que ça ne fait que 5.5 cm de différence sur plus d'un million de mètres, mais pour un homme 5 cm c'est important ...
J'ai testé r16 et r17, c'est la même chose. Est-ce que quelqu'un peut me confirmer ?
Dernière modification par oli_d ; 24/09/2015 à 20h48.
Merci val,
C'est pas top ce bug pour moi qui manipule pas mal de données géographiques avec ce genre de coordonnées ...
Je vais essayer de remonter ça sur PluginCafe avec mon english à deux balles