Commit 093f6a45 authored by kliment's avatar kliment

Merge pull request #279 from iXce/connection-rework

Connection rework, coding style rework
parents 7e2e6a51 107280b8
*.pyc *.pyc
.pronsolerc .pronsolerc
*.swp
*.bak
Some cleanup commands :
To add a space after each comma :
sed -e "s/\(\w\),\(\w\)/\1, \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\(\w\),\(\"\)/\1, \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\(\"\),\(\w\)/\1, \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\(\"\),\(\"\)/\1, \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\([)}\]]\),\(\w\)/\1, \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\([)}\]]\),\([\[{(]\)/\1, \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\(\w\),\([\[{(]\)/\1, \2/g" -i *.py printrun/*.py printrun/svg/*.py
To add spaces around each = :
sed -e "s/\(\w\)=\(\w\)/\1 = \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\(\w\)=\(\"\)/\1 = \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\(\w\)=\((\)/\1 = \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\(\w\)=\((\)/\1 = \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\(\w\)=\([\[{(]\)/\1 = \2/g" -i *.py printrun/*.py printrun/svg/*.py
To add spaces around each == :
sed -e "s/\(\w\)==\(\w\)/\1 == \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\(\w\)==\(\"\)/\1 == \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\(\w\)==\((\)/\1 == \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\()\)==\(\w\)/\1 == \2/g" -i *.py printrun/*.py printrun/svg/*.py
sed -e "s/\()\)==\((\)/\1 == \2/g" -i *.py printrun/*.py printrun/svg/*.py
Obviously this is not a perfect solution, it WILL break the code. Juste check the diff and fix what's wrong before commiting.
...@@ -10,7 +10,7 @@ The pronterface.py now uses gettext for the messages it generates. ...@@ -10,7 +10,7 @@ The pronterface.py now uses gettext for the messages it generates.
The corresponding pronterface.pot file is at locale/pronterface.pot The corresponding pronterface.pot file is at locale/pronterface.pot
and was generated using and was generated using
pygettext -o locale/pronterface.pot pronterface.py pygettext -o locale/pronterface.pot pronterface.py printrun/pronterface_widgets.py
followed by minor edits to the generated header. followed by minor edits to the generated header.
...@@ -20,14 +20,14 @@ now there is only one, for German. New ones can be created: ...@@ -20,14 +20,14 @@ now there is only one, for German. New ones can be created:
# Create new pronterface message catalog for a different language # Create new pronterface message catalog for a different language
newlang="es" # use the correct code for your language newlang="es" # use the correct code for your language
mkdir -p locale/${newlang}/LC_MESSAGES mkdir -p locale/${newlang}/LC_MESSAGES
cp locale/pronterface.pot locale/${newlanguage}/LC_MESSAGES/${newlang}.po cp locale/pronterface.pot locale/${newlanguage}/LC_MESSAGES/pronterface.po
cd locale/${newlanguage}/LC_MESSAGES/${newlang} cd locale/${newlanguage}/LC_MESSAGES/
# Edit the .po file to add messages for newlang # Edit the .po file to add messages for newlang
msgfmt -o ${newlang}.mo ${newlang}.po msgfmt -o pronterface.mo pronterface.po
To update a previously created message catalog from the template, use : To update a previously created message catalog from the template, use :
msgmerge -U locale/fr/LC_MESSAGES/${lang}.po locale/pronterface.pot msgmerge -U locale/fr/LC_MESSAGES/pronterface.po locale/pronterface.pot
As currently coded, the default location for these message catalogs is As currently coded, the default location for these message catalogs is
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Plater\n" "Project-Id-Version: Plater\n"
"POT-Creation-Date: 2012-02-26 02:40+CET\n" "POT-Creation-Date: 2012-08-04 21:53+CEST\n"
"PO-Revision-Date: 2012-02-26 02:41+0100\n" "PO-Revision-Date: 2012-02-26 02:41+0100\n"
"Last-Translator: Guillaume Seguin <guillaume@segu.in>\n" "Last-Translator: Guillaume Seguin <guillaume@segu.in>\n"
"Language-Team: FR <guillaume@segu.in>\n" "Language-Team: FR <guillaume@segu.in>\n"
...@@ -15,81 +15,81 @@ msgstr "" ...@@ -15,81 +15,81 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n" "Generated-By: pygettext.py 1.5\n"
#: plater.py:247 #: plater.py:246
msgid "Plate building tool" msgid "Plate building tool"
msgstr "Outil d'assemblage de plateau" msgstr "Outil d'assemblage de plateau"
#: plater.py:253 #: plater.py:252
msgid "Clear" msgid "Clear"
msgstr "Vider" msgstr "Vider"
#: plater.py:254 #: plater.py:253
msgid "Load" msgid "Load"
msgstr "Charger" msgstr "Charger"
#: plater.py:256 #: plater.py:255 plater.py:258
msgid "Export" msgid "Export"
msgstr "Exporter" msgstr "Exporter"
#: plater.py:259 #: plater.py:260
msgid "Done" msgid "Done"
msgstr "Terminé" msgstr "Terminé"
#: plater.py:261 #: plater.py:262
msgid "Cancel" msgid "Cancel"
msgstr "Annuler" msgstr "Annuler"
#: plater.py:263 #: plater.py:264
msgid "Snap to Z = 0" msgid "Snap to Z = 0"
msgstr "Poser en Z = 0" msgstr "Poser en Z = 0"
#: plater.py:264 #: plater.py:265
msgid "Put at 100, 100" msgid "Put at 100, 100"
msgstr "Placer en 100, 100" msgstr "Placer en 100, 100"
#: plater.py:265 #: plater.py:266
msgid "Delete" msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
#: plater.py:266 #: plater.py:267
msgid "Auto" msgid "Auto"
msgstr "Auto" msgstr "Auto"
#: plater.py:290 #: plater.py:291
msgid "Autoplating" msgid "Autoplating"
msgstr "Placement auto" msgstr "Placement auto"
#: plater.py:318 #: plater.py:319
msgid "Bed full, sorry sir :(" msgid "Bed full, sorry sir :("
msgstr "Le lit est plein, désolé :(" msgstr "Le lit est plein, désolé :("
#: plater.py:328 #: plater.py:329
msgid "" msgid ""
"Are you sure you want to clear the grid? All unsaved changes will be lost." "Are you sure you want to clear the grid? All unsaved changes will be lost."
msgstr "" msgstr ""
"Êtes vous sur de vouloir vider la grille ? Toutes les modifications non " "Êtes vous sur de vouloir vider la grille ? Toutes les modifications non "
"enregistrées seront perdues." "enregistrées seront perdues."
#: plater.py:328 #: plater.py:329
msgid "Clear the grid?" msgid "Clear the grid?"
msgstr "Vider la grille ?" msgstr "Vider la grille ?"
#: plater.py:370 #: plater.py:371
msgid "Pick file to save to" msgid "Pick file to save to"
msgstr "Choisir le fichier dans lequel enregistrer" msgstr "Choisir le fichier dans lequel enregistrer"
#: plater.py:371 #: plater.py:372
msgid "STL files (;*.stl;*.STL;)" msgid "STL files (;*.stl;*.STL;)"
msgstr "Fichiers STL (;*.stl;*.STL;)" msgstr "Fichiers STL (;*.stl;*.STL;)"
#: plater.py:391 #: plater.py:393
msgid "wrote %s" msgid "wrote %s"
msgstr "%s écrit" msgstr "%s écrit"
#: plater.py:394 #: plater.py:396
msgid "Pick file to load" msgid "Pick file to load"
msgstr "Choisir le fichier à charger" msgstr "Choisir le fichier à charger"
#: plater.py:395 #: plater.py:397
msgid "STL files (;*.stl;*.STL;)|*.stl|OpenSCAD files (;*.scad;)|*.scad" msgid "STL files (;*.stl;*.STL;)|*.stl|OpenSCAD files (;*.scad;)|*.scad"
msgstr "Fichiers STL (;*.stl;*.STL;)|*.stl|Fichiers OpenSCAD (;*.scad;)|*.scad" msgstr "Fichiers STL (;*.stl;*.STL;)|*.stl|Fichiers OpenSCAD (;*.scad;)|*.scad"
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Pronterface jm1\n" "Project-Id-Version: Pronterface jm1\n"
"POT-Creation-Date: 2012-03-16 03:48+CET\n" "POT-Creation-Date: 2012-08-08 10:09+CEST\n"
"PO-Revision-Date: 2012-03-16 03:50+0100\n" "PO-Revision-Date: 2012-03-16 03:50+0100\n"
"Last-Translator: Guillaume Seguin <guillaume@segu.in>\n" "Last-Translator: Guillaume Seguin <guillaume@segu.in>\n"
"Language-Team: FR <c.laguilhon.debat@gmail.com>\n" "Language-Team: FR <c.laguilhon.debat@gmail.com>\n"
...@@ -15,13 +15,49 @@ msgstr "" ...@@ -15,13 +15,49 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n" "Generated-By: pygettext.py 1.5\n"
#: pronterface.py:30 #: printrun/pronterface_widgets.py:34
msgid "Find"
msgstr "Trouver"
#: printrun/pronterface_widgets.py:36
msgid "Save"
msgstr "Enregistrer"
#: printrun/pronterface_widgets.py:41 pronterface.py:477 pronterface.py:1535
msgid "Cancel"
msgstr "Annuler"
#: printrun/pronterface_widgets.py:125
msgid "Edit settings"
msgstr "Modifier les paramètres"
#: printrun/pronterface_widgets.py:127
msgid "Defaults"
msgstr "Paramètres par défaut"
#: printrun/pronterface_widgets.py:156
msgid "Custom button"
msgstr "Commande personnalisée"
#: printrun/pronterface_widgets.py:161
msgid "Button title"
msgstr "Titre du bouton"
#: printrun/pronterface_widgets.py:164
msgid "Command"
msgstr "Commande"
#: printrun/pronterface_widgets.py:173
msgid "Color"
msgstr "Couleur"
#: pronterface.py:26
msgid "WX is not installed. This program requires WX to run." msgid "WX is not installed. This program requires WX to run."
msgstr "" msgstr ""
"wxWidgets n'est pas installé. Ce programme nécessite la librairie wxWidgets " "wxWidgets n'est pas installé. Ce programme nécessite la librairie wxWidgets "
"pour fonctionner." "pour fonctionner."
#: pronterface.py:81 #: pronterface.py:93
msgid "" msgid ""
"Dimensions of Build Platform\n" "Dimensions of Build Platform\n"
" & optional offset of origin\n" " & optional offset of origin\n"
...@@ -32,55 +68,71 @@ msgid "" ...@@ -32,55 +68,71 @@ msgid ""
" XXXxYYYxZZZ+OffX+OffY+OffZ" " XXXxYYYxZZZ+OffX+OffY+OffZ"
msgstr "" msgstr ""
#: pronterface.py:82 #: pronterface.py:94
msgid "Last Set Temperature for the Heated Print Bed" msgid "Last Set Temperature for the Heated Print Bed"
msgstr "Dernière température du plateau chauffant définie" msgstr "Dernière température du plateau chauffant définie"
#: pronterface.py:83 #: pronterface.py:95
msgid "Folder of last opened file" msgid "Folder of last opened file"
msgstr "Dossier du dernier fichier ouvert" msgstr "Dossier du dernier fichier ouvert"
#: pronterface.py:84 #: pronterface.py:96
msgid "Last Temperature of the Hot End" msgid "Last Temperature of the Hot End"
msgstr "Dernière température de la buse définie" msgstr "Dernière température de la buse définie"
#: pronterface.py:85 #: pronterface.py:97
msgid "Width of Extrusion in Preview (default: 0.5)" msgid "Width of Extrusion in Preview (default: 0.5)"
msgstr "Largeur de l'extrusion dans la prévisualisation (défaut : 0.5)" msgstr "Largeur de l'extrusion dans la prévisualisation (défaut : 0.5)"
#: pronterface.py:86 #: pronterface.py:98
msgid "Fine Grid Spacing (default: 10)" msgid "Fine Grid Spacing (default: 10)"
msgstr "Espacement fin de la grille (défaut : 10)" msgstr "Espacement fin de la grille (défaut : 10)"
#: pronterface.py:87 #: pronterface.py:99
msgid "Coarse Grid Spacing (default: 50)" msgid "Coarse Grid Spacing (default: 50)"
msgstr "Espacement large de la grille (défaut : 50)" msgstr "Espacement large de la grille (défaut : 50)"
#: pronterface.py:88 #: pronterface.py:100
msgid "Pronterface background color (default: #FFFFFF)" msgid "Pronterface background color (default: #FFFFFF)"
msgstr "Couleur de fond de la Pronterface (défaut : #FFFFFF)" msgstr "Couleur de fond de la Pronterface (défaut : #FFFFFF)"
#: pronterface.py:91 #: pronterface.py:103
msgid "Printer Interface" msgid "Printer Interface"
msgstr "Interface de l'imprimante" msgstr "Interface de l'imprimante"
#: pronterface.py:109 #: pronterface.py:122
msgid "Motors off" msgid "Motors off"
msgstr "Arrêter les moteurs" msgstr "Arrêter les moteurs"
#: pronterface.py:110 #: pronterface.py:122
msgid "Switch all motors off"
msgstr "Arrêter tous les moteurs"
#: pronterface.py:123
msgid "Check current hotend temperature"
msgstr "Vérifier la température actuelle de la buse"
#: pronterface.py:123
msgid "Check temp" msgid "Check temp"
msgstr "Lire les températures" msgstr "Lire les températures"
#: pronterface.py:111 #: pronterface.py:124
msgid "Advance extruder by set length"
msgstr "Extruder sur la longueur donnée"
#: pronterface.py:124
msgid "Extrude" msgid "Extrude"
msgstr "Extruder" msgstr "Extruder"
#: pronterface.py:112 #: pronterface.py:125
msgid "Reverse" msgid "Reverse"
msgstr "Inverser" msgstr "Inverser"
#: pronterface.py:130 #: pronterface.py:125
msgid "Reverse extruder by set length"
msgstr "Inverser l'extrudeur sur la longueur donnée"
#: pronterface.py:143
msgid "" msgid ""
"# I moved all your custom buttons into .pronsolerc.\n" "# I moved all your custom buttons into .pronsolerc.\n"
"# Please don't add them here any more.\n" "# Please don't add them here any more.\n"
...@@ -91,7 +143,7 @@ msgstr "" ...@@ -91,7 +143,7 @@ msgstr ""
"# Veuillez ne plus en ajouter ici.\n" "# Veuillez ne plus en ajouter ici.\n"
"# Une sauvegarde de vos anciens boutons est dans le fichier custombtn.old\n" "# Une sauvegarde de vos anciens boutons est dans le fichier custombtn.old\n"
#: pronterface.py:135 #: pronterface.py:148
msgid "" msgid ""
"Note!!! You have specified custom buttons in both custombtn.txt and ." "Note!!! You have specified custom buttons in both custombtn.txt and ."
"pronsolerc" "pronsolerc"
...@@ -99,36 +151,44 @@ msgstr "" ...@@ -99,36 +151,44 @@ msgstr ""
"Remarque! Vous avez spécifié des boutons personnalisés dans custombtn.txt et " "Remarque! Vous avez spécifié des boutons personnalisés dans custombtn.txt et "
"aussi dans .pronsolerc" "aussi dans .pronsolerc"
#: pronterface.py:136 #: pronterface.py:149
msgid "" msgid ""
"Ignoring custombtn.txt. Remove all current buttons to revert to custombtn.txt" "Ignoring custombtn.txt. Remove all current buttons to revert to custombtn.txt"
msgstr "" msgstr ""
"custombtn.txt ignoré. Retirez tous les boutons en cours pour revenir à " "custombtn.txt ignoré. Retirez tous les boutons en cours pour revenir à "
"custombtn.txt" "custombtn.txt"
#: pronterface.py:165 pronterface.py:520 pronterface.py:1343 #: pronterface.py:181
#: pronterface.py:1397 pronterface.py:1521 pronterface.py:1555 msgid "Failed to start web interface"
#: pronterface.py:1567 msgstr "Échec du lancement de l'interface web"
#: pronterface.py:185
msgid "CherryPy is not installed. Web Interface Disabled."
msgstr "CherryPy n'est pas installé. L'interface web est désactivée."
#: pronterface.py:197 pronterface.py:603 pronterface.py:1525
#: pronterface.py:1578 pronterface.py:1705 pronterface.py:1765
#: pronterface.py:1778
msgid "Print" msgid "Print"
msgstr "Imprimer" msgstr "Imprimer"
#: pronterface.py:169 #: pronterface.py:207
msgid "Printer is now online." msgid "Printer is now online."
msgstr "L'imprimante est connectée" msgstr "Imprimante connectée."
#: pronterface.py:170 #: pronterface.py:208
msgid "Disconnect" msgid "Disconnect"
msgstr "Déconnecter" msgstr "Déconnecter"
#: pronterface.py:229 #: pronterface.py:331
msgid "Setting hotend temperature to %f degrees Celsius." msgid "Setting hotend temperature to %f degrees Celsius."
msgstr "Réglage de la température de la buse à %f degrés Celsius." msgstr "Réglage de la température de la buse à %f degrés Celsius."
#: pronterface.py:248 pronterface.py:284 pronterface.py:346 #: pronterface.py:334 pronterface.py:356 pronterface.py:428
msgid "Printer is not online." msgid "Printer is not online."
msgstr "L'imprimante est déconnectée" msgstr "Imprimante déconnectée."
#: pronterface.py:250 #: pronterface.py:336
msgid "" msgid ""
"You cannot set negative temperatures. To turn the hotend off entirely, set " "You cannot set negative temperatures. To turn the hotend off entirely, set "
"its temperature to 0." "its temperature to 0."
...@@ -136,15 +196,15 @@ msgstr "" ...@@ -136,15 +196,15 @@ msgstr ""
"Vous ne pouvez pas régler une température négative. Pour éteindre la buse, " "Vous ne pouvez pas régler une température négative. Pour éteindre la buse, "
"réglez sa température à 0°C." "réglez sa température à 0°C."
#: pronterface.py:252 #: pronterface.py:338 pronterface.py:364
msgid "You must enter a temperature. (%s)" msgid "You must enter a temperature. (%s)"
msgstr "Vous devez saisir une température. (%s)" msgstr "Vous devez saisir une température. (%s)"
#: pronterface.py:265 #: pronterface.py:353
msgid "Setting bed temperature to %f degrees Celsius." msgid "Setting bed temperature to %f degrees Celsius."
msgstr "Réglage de la température du plateau à %f degrés Celsius." msgstr "Réglage de la température du plateau à %f degrés Celsius."
#: pronterface.py:286 #: pronterface.py:360
msgid "" msgid ""
"You cannot set negative temperatures. To turn the bed off entirely, set its " "You cannot set negative temperatures. To turn the bed off entirely, set its "
"temperature to 0." "temperature to 0."
...@@ -152,343 +212,328 @@ msgstr "" ...@@ -152,343 +212,328 @@ msgstr ""
"Vous ne pouvez pas régler une température négative. Pour désactiver votre " "Vous ne pouvez pas régler une température négative. Pour désactiver votre "
"plateau chauffant, réglez sa température à 0°C." "plateau chauffant, réglez sa température à 0°C."
#: pronterface.py:288 #: pronterface.py:381
msgid "You must enter a temperature."
msgstr "Vous devez saisir une température."
#: pronterface.py:303
msgid "Do you want to erase the macro?" msgid "Do you want to erase the macro?"
msgstr "Voulez-vous effacer la macro ?" msgstr "Voulez-vous effacer la macro ?"
#: pronterface.py:307 #: pronterface.py:385
msgid "Cancelled." msgid "Cancelled."
msgstr "Annulé" msgstr "Annulé"
#: pronterface.py:352 #: pronterface.py:436
msgid " Opens file" msgid " Opens file"
msgstr " Ouvrir un fichier" msgstr " Ouvrir un fichier"
#: pronterface.py:352 #: pronterface.py:436
msgid "&Open..." msgid "&Open..."
msgstr "&Ouvrir..." msgstr "&Ouvrir..."
#: pronterface.py:353 #: pronterface.py:437
msgid " Edit open file" msgid " Edit open file"
msgstr " Éditer le fichier ouvert" msgstr " Éditer le fichier ouvert"
#: pronterface.py:353 #: pronterface.py:437
msgid "&Edit..." msgid "&Edit..."
msgstr "&Éditer..." msgstr "&Éditer..."
#: pronterface.py:354 #: pronterface.py:438
msgid " Clear output console" msgid " Clear output console"
msgstr " Effacer le contenu de la console de sortie" msgstr " Effacer le contenu de la console de sortie"
#: pronterface.py:354 #: pronterface.py:438
msgid "Clear console" msgid "Clear console"
msgstr "Effacer la console" msgstr "Effacer la console"
#: pronterface.py:355 #: pronterface.py:439
msgid " Project slices" msgid " Project slices"
msgstr " Projeter les couches" msgstr " Projeter les couches"
#: pronterface.py:355 #: pronterface.py:439
msgid "Projector" msgid "Projector"
msgstr "Projecteur" msgstr "Projecteur"
#: pronterface.py:356 #: pronterface.py:440
msgid " Closes the Window" msgid " Closes the Window"
msgstr " Quitter le programme" msgstr " Quitter le programme"
#: pronterface.py:356 #: pronterface.py:440
msgid "E&xit" msgid "E&xit"
msgstr "&Quitter" msgstr "&Quitter"
#: pronterface.py:357 #: pronterface.py:441
msgid "&File" msgid "&File"
msgstr "&Fichier" msgstr "&Fichier"
#: pronterface.py:362 #: pronterface.py:446
msgid "&Macros" msgid "&Macros"
msgstr "&Macros" msgstr "&Macros"
#: pronterface.py:363 #: pronterface.py:447
msgid "<&New...>" msgid "<&New...>"
msgstr "<&Nouvelle...>" msgstr "<&Nouvelle...>"
#: pronterface.py:364 #: pronterface.py:448
msgid " Options dialog" msgid " Options dialog"
msgstr " Fenêtre des options" msgstr " Fenêtre des options"
#: pronterface.py:364 #: pronterface.py:448
msgid "&Options" msgid "&Options"
msgstr "&Options" msgstr "&Options"
#: pronterface.py:366 #: pronterface.py:450
msgid " Adjust slicing settings" msgid " Adjust slicing settings"
msgstr " Régler les paramètres de slicing" msgstr " Régler les paramètres de slicing"
#: pronterface.py:366 #: pronterface.py:450
msgid "Slicing Settings" msgid "Slicing Settings"
msgstr "Paramètres de slicing" msgstr "Paramètres de slicing"
#: pronterface.py:373 #: pronterface.py:452
msgid "&Settings" msgid "&Settings"
msgstr "&Paramètres" msgstr "&Paramètres"
#: pronterface.py:389 #: pronterface.py:467
msgid "Enter macro name" msgid "Enter macro name"
msgstr "Saisissez le nom de la macro" msgstr "Saisissez le nom de la macro"
#: pronterface.py:392 #: pronterface.py:470
msgid "Macro name:" msgid "Macro name:"
msgstr "Nom :" msgstr "Nom :"
#: pronterface.py:395 #: pronterface.py:473
msgid "Ok" msgid "Ok"
msgstr "Valider" msgstr "Valider"
#: pronterface.py:399 pronterface.py:1354 pronterface.py:1613 #: pronterface.py:495
msgid "Cancel" msgid "Macro name may contain only ASCII alphanumeric symbols and underscores"
msgstr "Annuler" msgstr ""
"Un nom de macro ne peut contenir que des caractères alphanumérique ASCII et "
"des underscore (_)"
#: pronterface.py:417 #: pronterface.py:500
msgid "Name '%s' is being used by built-in command" msgid "Name '%s' is being used by built-in command"
msgstr "Le nom '%s' est utilisé par une commande interne" msgstr "Le nom '%s' est utilisé par une commande interne"
#: pronterface.py:420 #: pronterface.py:548
msgid "Macro name may contain only alphanumeric symbols and underscores"
msgstr ""
"Un nom de macro ne peut contenir que des caractères alphanumérique et des "
"underscore (_)"
#: pronterface.py:469
msgid "Port" msgid "Port"
msgstr "Port" msgstr "Port"
#: pronterface.py:488 #: pronterface.py:570 pronterface.py:1747
msgid "Connect" msgid "Connect"
msgstr "Connecter" msgstr "Connecter"
#: pronterface.py:490 #: pronterface.py:574
msgid "Connect to the printer"
msgstr "Connecter l'imprimante"
#: pronterface.py:492
msgid "Reset" msgid "Reset"
msgstr "Réinitialiser" msgstr "Réinitialiser"
#: pronterface.py:495 pronterface.py:772 #: pronterface.py:589
msgid "Mini mode"
msgstr "Mode réduit"
#: pronterface.py:499
msgid "Monitor Printer"
msgstr "Surveiller l'imprimante"
#: pronterface.py:509
msgid "Load file" msgid "Load file"
msgstr "Charger un fichier" msgstr "Charger un fichier"
#: pronterface.py:512 #: pronterface.py:593
msgid "Compose" msgid "Compose"
msgstr "Composer" msgstr "Composer"
#: pronterface.py:516 #: pronterface.py:598
msgid "SD" msgid "SD"
msgstr "SD" msgstr "SD"
#: pronterface.py:524 pronterface.py:1398 pronterface.py:1444 #: pronterface.py:608 pronterface.py:1579 pronterface.py:1631
#: pronterface.py:1495 pronterface.py:1520 pronterface.py:1554 #: pronterface.py:1681 pronterface.py:1704 pronterface.py:1764
#: pronterface.py:1570 #: pronterface.py:1781
msgid "Pause" msgid "Pause"
msgstr "Pause" msgstr "Pause"
#: pronterface.py:537 #: pronterface.py:612
msgid "Recover"
msgstr "Récupérer"
#: pronterface.py:630
msgid "Send" msgid "Send"
msgstr "Envoyer" msgstr "Envoyer"
#: pronterface.py:545 pronterface.py:646 #: pronterface.py:671
msgid "mm/min"
msgstr "mm/min"
#: pronterface.py:547
msgid "XY:" msgid "XY:"
msgstr "XY:" msgstr "XY:"
#: pronterface.py:549 #: pronterface.py:673
msgid "Z:" msgid "mm/min Z:"
msgstr "Z:" msgstr "mm/min Z:"
#: pronterface.py:572 pronterface.py:653 #: pronterface.py:678
msgid "Heater:" msgid "Watch"
msgstr "Buse :" msgstr "Surveiller"
#: pronterface.py:575 pronterface.py:595 #: pronterface.py:683
msgid "Heat:"
msgstr "Buse:"
#: pronterface.py:686 pronterface.py:709
msgid "Off" msgid "Off"
msgstr "Off" msgstr "Off"
#: pronterface.py:587 pronterface.py:607 #: pronterface.py:700 pronterface.py:723
msgid "Set" msgid "Set"
msgstr "Régler" msgstr "Régler"
#: pronterface.py:592 pronterface.py:655 #: pronterface.py:706
msgid "Bed:" msgid "Bed:"
msgstr "Plateau :" msgstr "Plateau :"
#: pronterface.py:640 #: pronterface.py:756
msgid "mm" msgid "mm"
msgstr "mm" msgstr "mm"
#: pronterface.py:698 pronterface.py:1206 pronterface.py:1438 #: pronterface.py:764
msgid ""
"mm/\n"
"min"
msgstr ""
"mm/\n"
"min"
#: pronterface.py:821 pronterface.py:1387 pronterface.py:1625
#: pronterface.py:1723
msgid "Not connected to printer." msgid "Not connected to printer."
msgstr "Imprimante non connectée." msgstr "Imprimante non connectée."
#: pronterface.py:727 #: pronterface.py:869
msgid "SD Upload" msgid "SD Upload"
msgstr "Copier sur SD" msgstr "Copier sur SD"
#: pronterface.py:731 #: pronterface.py:873
msgid "SD Print" msgid "SD Print"
msgstr "Imprimer depuis SD" msgstr "Imprimer depuis SD"
#: pronterface.py:779 #: pronterface.py:914
msgid "Mini mode"
msgstr "Mode réduit"
#: pronterface.py:921
msgid "Full mode" msgid "Full mode"
msgstr "Mode complet" msgstr "Mode complet"
#: pronterface.py:804 #: pronterface.py:946
msgid "Execute command: " msgid "Execute command: "
msgstr "Exécuter la commande :" msgstr "Exécuter la commande :"
#: pronterface.py:815 #: pronterface.py:957
msgid "click to add new custom button" msgid "click to add new custom button"
msgstr "Ajouter un bouton personnalisé" msgstr "Ajouter un bouton personnalisé"
#: pronterface.py:834 #: pronterface.py:979
msgid "" msgid ""
"Defines custom button. Usage: button <num> \"title\" [/c \"colour\"] command" "Defines custom button. Usage: button <num> \"title\" [/c \"colour\"] command"
msgstr "" msgstr ""
"Définit des boutons personnalidés. Utilisation : <numero> \"Libelle\" [/c " "Définit des boutons personnalidés. Utilisation : <numero> \"Libelle\" [/c "
"\"couleur\"] commande" "\"couleur\"] commande"
#: pronterface.py:856 #: pronterface.py:1003
msgid "Custom button number should be between 0 and 63" msgid "Custom button number should be between 0 and 63"
msgstr "" msgstr ""
"Les numéros des boutons personnalisés doivent être compris entre 0 et 63." "Les numéros des boutons personnalisés doivent être compris entre 0 et 63."
#: pronterface.py:948 #: pronterface.py:1096
msgid "Edit custom button '%s'" msgid "Edit custom button '%s'"
msgstr "Editer le bouton personnalisé '%s'" msgstr "Editer le bouton personnalisé '%s'"
#: pronterface.py:950 #: pronterface.py:1098
msgid "Move left <<" msgid "Move left <<"
msgstr "Déplacer vers la gauche <<" msgstr "Déplacer vers la gauche <<"
#: pronterface.py:953 #: pronterface.py:1101
msgid "Move right >>" msgid "Move right >>"
msgstr "Déplacer vers la droite >>" msgstr "Déplacer vers la droite >>"
#: pronterface.py:957 #: pronterface.py:1105
msgid "Remove custom button '%s'" msgid "Remove custom button '%s'"
msgstr "Supprimer le bouton personnalisé '%s'" msgstr "Supprimer le bouton personnalisé '%s'"
#: pronterface.py:960 #: pronterface.py:1108
msgid "Add custom button" msgid "Add custom button"
msgstr "Ajouter un bouton personnalisé" msgstr "Ajouter un bouton personnalisé"
#: pronterface.py:1105 #: pronterface.py:1270
msgid "event object missing" msgid "event object missing"
msgstr "événement d'objet manquant" msgstr "événement d'objet manquant"
#: pronterface.py:1133 #: pronterface.py:1306
msgid "Invalid period given." msgid "Invalid period given."
msgstr "La période donnée est invalide" msgstr "La période donnée est invalide"
#: pronterface.py:1136 #: pronterface.py:1311
msgid "Monitoring printer." msgid "Monitoring printer."
msgstr "Imprimante sous surveillance." msgstr "Imprimante sous surveillance."
#: pronterface.py:1138 #: pronterface.py:1315
msgid "Done monitoring." msgid "Done monitoring."
msgstr "Surveillance de l'imprimante effectuée." msgstr "Surveillance de l'imprimante effectuée."
#: pronterface.py:1160 #: pronterface.py:1355
msgid "Printer is online. "
msgstr "L'imprimante est connectée. "
#: pronterface.py:1162 pronterface.py:1341
msgid "Loaded "
msgstr "Chargé "
#: pronterface.py:1165
msgid "Bed"
msgstr "Plateau"
#: pronterface.py:1165
msgid "Hotend"
msgstr "Buse"
#: pronterface.py:1175
msgid " SD printing:%04.2f %%" msgid " SD printing:%04.2f %%"
msgstr " Impression SD : %04.2f %%" msgstr " Impression SD : %04.2f %%"
#: pronterface.py:1178 #: pronterface.py:1358
msgid " Printing:%04.2f %% |" msgid " Printing: %04.2f%% |"
msgstr " Impression : %04.2f %% |" msgstr " Impression : %04.2f%% |"
#: pronterface.py:1179 #: pronterface.py:1359
msgid " Line# %d of %d lines |" msgid " Line# %d of %d lines |"
msgstr " Ligne# %d sur %d lignes |" msgstr " Ligne# %d sur %d lignes |"
#: pronterface.py:1184 #: pronterface.py:1364
msgid " Est: %s of %s remaining | " msgid " Est: %s of %s remaining | "
msgstr " ETA: %s restant sur %s | " msgstr " ETA: %s restant sur %s | "
#: pronterface.py:1186 #: pronterface.py:1366
msgid " Z: %0.2f mm" msgid " Z: %0.2f mm"
msgstr " Z: %0.2f mm" msgstr " Z: %0.2f mm"
#: pronterface.py:1257 #: pronterface.py:1439
msgid "Opening file failed." msgid "Opening file failed."
msgstr "L'ouverture du fichier a échoué" msgstr "L'ouverture du fichier a échoué"
#: pronterface.py:1263 #: pronterface.py:1445
msgid "Starting print" msgid "Starting print"
msgstr "Début de l'impression..." msgstr "Début de l'impression..."
#: pronterface.py:1286 #: pronterface.py:1466
msgid "Pick SD file" msgid "Pick SD file"
msgstr "Choisir un fichier sur la carte SD" msgstr "Choisir un fichier sur la carte SD"
#: pronterface.py:1286 #: pronterface.py:1466
msgid "Select the file to print" msgid "Select the file to print"
msgstr "Sélectionnez le fichier à imprimer :" msgstr "Sélectionnez le fichier à imprimer :"
#: pronterface.py:1321 #: pronterface.py:1501
msgid "Failed to execute slicing software: " msgid "Failed to execute slicing software: "
msgstr "Une erreur s'est produite lors du slicing : " msgstr "Une erreur s'est produite lors du slicing : "
#: pronterface.py:1328 #: pronterface.py:1510
msgid "Slicing..." msgid "Slicing..."
msgstr "Slicing..." msgstr "Slicing..."
#: pronterface.py:1341 #: pronterface.py:1523
msgid ", %d lines" msgid ", %d lines"
msgstr ", %d lignes" msgstr ", %d lignes"
#: pronterface.py:1348 #: pronterface.py:1523
msgid "Loaded "
msgstr "Chargé "
#: pronterface.py:1530
msgid "Load File" msgid "Load File"
msgstr "Charger un fichier" msgstr "Charger un fichier"
#: pronterface.py:1355 #: pronterface.py:1536
msgid "Slicing " msgid "Slicing "
msgstr "Slicing " msgstr "Slicing "
#: pronterface.py:1374 #: pronterface.py:1555
msgid "Open file to print" msgid "Open file to print"
msgstr "Ouvrir un fichier à imprimer" msgstr "Ouvrir un fichier à imprimer"
#: pronterface.py:1375 #: pronterface.py:1556
msgid "" msgid ""
"OBJ, STL, and GCODE files (*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ)|*." "OBJ, STL, and GCODE files (*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ)|*."
"gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|All Files (*.*)|*.*" "gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|All Files (*.*)|*.*"
...@@ -496,114 +541,86 @@ msgstr "" ...@@ -496,114 +541,86 @@ msgstr ""
"Fichiers OBJ, STL et GCODE (;*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ;)|*." "Fichiers OBJ, STL et GCODE (;*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ;)|*."
"gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|Tous les fichiers (*.*)|*.*" "gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|Tous les fichiers (*.*)|*.*"
#: pronterface.py:1382 #: pronterface.py:1563
msgid "File not found!" msgid "File not found!"
msgstr "Fichier non trouvé" msgstr "Fichier non trouvé"
#: pronterface.py:1396 #: pronterface.py:1577
msgid "Loaded %s, %d lines" msgid "Loaded %s, %d lines"
msgstr "%s chargé, %d lignes" msgstr "%s chargé, %d lignes"
#: pronterface.py:1406 #: pronterface.py:1588
msgid "mm of filament used in this print\n" msgid "mm of filament used in this print\n"
msgstr "mm de filament utilisés pour cette impression\n" msgstr "mm de filament utilisés pour cette impression\n"
#: pronterface.py:1407 #: pronterface.py:1589 pronterface.py:1591
msgid "" msgid ""
"the print goes from %f mm to %f mm in X\n" "the print goes from %f mm to %f mm in X\n"
"and is %f mm wide\n" "and is %f mm wide\n"
msgstr "" msgstr ""
"L'impression va de %f mm à %f m en X\n" "L'impression va de %f mm à %f mm en X\n"
"et mesure %f mm de large\n" "et mesure %f mm de large\n"
#: pronterface.py:1408 #: pronterface.py:1592
msgid "" msgid ""
"the print goes from %f mm to %f mm in Y\n" "the print goes from %f mm to %f mm in Y\n"
"and is %f mm wide\n" "and is %f mm wide\n"
msgstr "" msgstr ""
"L'impression va de %f mm à %f m en Y\n" "L'impression va de %f mm à %f mm en Y\n"
"et mesure %f mm de large\n" "et mesure %f mm de large\n"
#: pronterface.py:1409 #: pronterface.py:1593
msgid "" msgid ""
"the print goes from %f mm to %f mm in Z\n" "the print goes from %f mm to %f mm in Z\n"
"and is %f mm high\n" "and is %f mm high\n"
msgstr "" msgstr ""
"L'impression va de %f mm à %f m en Y\n" "L'impression va de %f mm à %f mm en Y\n"
"et mesure %f mm de haut\n" "et mesure %f mm de haut\n"
#: pronterface.py:1410 #: pronterface.py:1595
msgid "Estimated duration (pessimistic): " msgid "Estimated duration (pessimistic): "
msgstr "Durée estimée (pessimiste) : " msgstr "Durée estimée (pessimiste) : "
#: pronterface.py:1435 #: pronterface.py:1622
msgid "No file loaded. Please use load first." msgid "No file loaded. Please use load first."
msgstr "Aucun fichier chargé. Veuillez charger un fichier avant." msgstr "Aucun fichier chargé. Veuillez charger un fichier avant."
#: pronterface.py:1446 #: pronterface.py:1633
msgid "Restart" msgid "Restart"
msgstr "Recommencer" msgstr "Recommencer"
#: pronterface.py:1450 #: pronterface.py:1637
msgid "File upload complete" msgid "File upload complete"
msgstr "Envoi du fichier terminé" msgstr "Envoi du fichier terminé"
#: pronterface.py:1469 #: pronterface.py:1656
msgid "Pick SD filename" msgid "Pick SD filename"
msgstr "Lister les fichiers sur la carte SD" msgstr "Lister les fichiers sur la carte SD"
#: pronterface.py:1477 #: pronterface.py:1663
msgid "Paused." msgid "Paused."
msgstr "En pause." msgstr "En pause."
#: pronterface.py:1488 #: pronterface.py:1674
msgid "Resume" msgid "Resume"
msgstr "Reprendre" msgstr "Reprendre"
#: pronterface.py:1504 #: pronterface.py:1688
msgid "Connecting..." msgid "Connecting..."
msgstr "Connection en cours..." msgstr "Connexion en cours..."
#: pronterface.py:1535 #: pronterface.py:1738
msgid "Disconnected." msgid "Disconnected."
msgstr "Déconnecté." msgstr "Déconnecté."
#: pronterface.py:1562 #: pronterface.py:1771
msgid "Reset." msgid "Reset."
msgstr "Réinitialisée." msgstr "Réinitialisée."
#: pronterface.py:1563 #: pronterface.py:1772
msgid "Are you sure you want to reset the printer?" msgid "Are you sure you want to reset the printer?"
msgstr "Etes-vous sûr de vouloir réinitialiser l'imprimante?" msgstr "Etes-vous sûr de vouloir réinitialiser l'imprimante?"
#: pronterface.py:1563 #: pronterface.py:1772
msgid "Reset?" msgid "Reset?"
msgstr "Réinitialiser ?" msgstr "Réinitialiser ?"
#: pronterface.py:1609
msgid "Save"
msgstr "Enregistrer"
#: pronterface.py:1665
msgid "Edit settings"
msgstr "Modifier les paramètres"
#: pronterface.py:1667
msgid "Defaults"
msgstr "Paramètres par défaut"
#: pronterface.py:1696
msgid "Custom button"
msgstr "Commande personnalisée"
#: pronterface.py:1701
msgid "Button title"
msgstr "Titre du bouton"
#: pronterface.py:1704
msgid "Command"
msgstr "Commande"
#: pronterface.py:1713
msgid "Color"
msgstr "Couleur"
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2012-02-26 02:40+CET\n" "POT-Creation-Date: 2012-08-04 21:53+CEST\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -15,79 +15,79 @@ msgstr "" ...@@ -15,79 +15,79 @@ msgstr ""
"Generated-By: pygettext.py 1.5\n" "Generated-By: pygettext.py 1.5\n"
#: plater.py:247 #: plater.py:246
msgid "Plate building tool" msgid "Plate building tool"
msgstr "" msgstr ""
#: plater.py:253 #: plater.py:252
msgid "Clear" msgid "Clear"
msgstr "" msgstr ""
#: plater.py:254 #: plater.py:253
msgid "Load" msgid "Load"
msgstr "" msgstr ""
#: plater.py:256 #: plater.py:255 plater.py:258
msgid "Export" msgid "Export"
msgstr "" msgstr ""
#: plater.py:259 #: plater.py:260
msgid "Done" msgid "Done"
msgstr "" msgstr ""
#: plater.py:261 #: plater.py:262
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
#: plater.py:263 #: plater.py:264
msgid "Snap to Z = 0" msgid "Snap to Z = 0"
msgstr "" msgstr ""
#: plater.py:264 #: plater.py:265
msgid "Put at 100, 100" msgid "Put at 100, 100"
msgstr "" msgstr ""
#: plater.py:265 #: plater.py:266
msgid "Delete" msgid "Delete"
msgstr "" msgstr ""
#: plater.py:266 #: plater.py:267
msgid "Auto" msgid "Auto"
msgstr "" msgstr ""
#: plater.py:290 #: plater.py:291
msgid "Autoplating" msgid "Autoplating"
msgstr "" msgstr ""
#: plater.py:318 #: plater.py:319
msgid "Bed full, sorry sir :(" msgid "Bed full, sorry sir :("
msgstr "" msgstr ""
#: plater.py:328 #: plater.py:329
msgid "Are you sure you want to clear the grid? All unsaved changes will be lost." msgid "Are you sure you want to clear the grid? All unsaved changes will be lost."
msgstr "" msgstr ""
#: plater.py:328 #: plater.py:329
msgid "Clear the grid?" msgid "Clear the grid?"
msgstr "" msgstr ""
#: plater.py:370 #: plater.py:371
msgid "Pick file to save to" msgid "Pick file to save to"
msgstr "" msgstr ""
#: plater.py:371 #: plater.py:372
msgid "STL files (;*.stl;*.STL;)" msgid "STL files (;*.stl;*.STL;)"
msgstr "" msgstr ""
#: plater.py:391 #: plater.py:393
msgid "wrote %s" msgid "wrote %s"
msgstr "" msgstr ""
#: plater.py:394 #: plater.py:396
msgid "Pick file to load" msgid "Pick file to load"
msgstr "" msgstr ""
#: plater.py:395 #: plater.py:397
msgid "STL files (;*.stl;*.STL;)|*.stl|OpenSCAD files (;*.scad;)|*.scad" msgid "STL files (;*.stl;*.STL;)|*.stl|OpenSCAD files (;*.scad;)|*.scad"
msgstr "" msgstr ""
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2012-03-16 03:48+CET\n" "POT-Creation-Date: 2012-08-08 10:09+CEST\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -15,11 +15,47 @@ msgstr "" ...@@ -15,11 +15,47 @@ msgstr ""
"Generated-By: pygettext.py 1.5\n" "Generated-By: pygettext.py 1.5\n"
#: pronterface.py:30 #: printrun/pronterface_widgets.py:34
msgid "Find"
msgstr ""
#: printrun/pronterface_widgets.py:36
msgid "Save"
msgstr ""
#: printrun/pronterface_widgets.py:41 pronterface.py:477 pronterface.py:1535
msgid "Cancel"
msgstr ""
#: printrun/pronterface_widgets.py:125
msgid "Edit settings"
msgstr ""
#: printrun/pronterface_widgets.py:127
msgid "Defaults"
msgstr ""
#: printrun/pronterface_widgets.py:156
msgid "Custom button"
msgstr ""
#: printrun/pronterface_widgets.py:161
msgid "Button title"
msgstr ""
#: printrun/pronterface_widgets.py:164
msgid "Command"
msgstr ""
#: printrun/pronterface_widgets.py:173
msgid "Color"
msgstr ""
#: pronterface.py:26
msgid "WX is not installed. This program requires WX to run." msgid "WX is not installed. This program requires WX to run."
msgstr "" msgstr ""
#: pronterface.py:81 #: pronterface.py:93
msgid "" msgid ""
"Dimensions of Build Platform\n" "Dimensions of Build Platform\n"
" & optional offset of origin\n" " & optional offset of origin\n"
...@@ -30,545 +66,524 @@ msgid "" ...@@ -30,545 +66,524 @@ msgid ""
" XXXxYYYxZZZ+OffX+OffY+OffZ" " XXXxYYYxZZZ+OffX+OffY+OffZ"
msgstr "" msgstr ""
#: pronterface.py:82 #: pronterface.py:94
msgid "Last Set Temperature for the Heated Print Bed" msgid "Last Set Temperature for the Heated Print Bed"
msgstr "" msgstr ""
#: pronterface.py:83 #: pronterface.py:95
msgid "Folder of last opened file" msgid "Folder of last opened file"
msgstr "" msgstr ""
#: pronterface.py:84 #: pronterface.py:96
msgid "Last Temperature of the Hot End" msgid "Last Temperature of the Hot End"
msgstr "" msgstr ""
#: pronterface.py:85 #: pronterface.py:97
msgid "Width of Extrusion in Preview (default: 0.5)" msgid "Width of Extrusion in Preview (default: 0.5)"
msgstr "" msgstr ""
#: pronterface.py:86 #: pronterface.py:98
msgid "Fine Grid Spacing (default: 10)" msgid "Fine Grid Spacing (default: 10)"
msgstr "" msgstr ""
#: pronterface.py:87 #: pronterface.py:99
msgid "Coarse Grid Spacing (default: 50)" msgid "Coarse Grid Spacing (default: 50)"
msgstr "" msgstr ""
#: pronterface.py:88 #: pronterface.py:100
msgid "Pronterface background color (default: #FFFFFF)" msgid "Pronterface background color (default: #FFFFFF)"
msgstr "" msgstr ""
#: pronterface.py:91 #: pronterface.py:103
msgid "Printer Interface" msgid "Printer Interface"
msgstr "" msgstr ""
#: pronterface.py:109 #: pronterface.py:122
msgid "Motors off" msgid "Motors off"
msgstr "" msgstr ""
#: pronterface.py:110 #: pronterface.py:122
msgid "Switch all motors off"
msgstr ""
#: pronterface.py:123
msgid "Check current hotend temperature"
msgstr ""
#: pronterface.py:123
msgid "Check temp" msgid "Check temp"
msgstr "" msgstr ""
#: pronterface.py:111 #: pronterface.py:124
msgid "Advance extruder by set length"
msgstr ""
#: pronterface.py:124
msgid "Extrude" msgid "Extrude"
msgstr "" msgstr ""
#: pronterface.py:112 #: pronterface.py:125
msgid "Reverse" msgid "Reverse"
msgstr "" msgstr ""
#: pronterface.py:130 #: pronterface.py:125
msgid "Reverse extruder by set length"
msgstr ""
#: pronterface.py:143
msgid "" msgid ""
"# I moved all your custom buttons into .pronsolerc.\n" "# I moved all your custom buttons into .pronsolerc.\n"
"# Please don't add them here any more.\n" "# Please don't add them here any more.\n"
"# Backup of your old buttons is in custombtn.old\n" "# Backup of your old buttons is in custombtn.old\n"
msgstr "" msgstr ""
#: pronterface.py:135 #: pronterface.py:148
msgid "Note!!! You have specified custom buttons in both custombtn.txt and .pronsolerc" msgid "Note!!! You have specified custom buttons in both custombtn.txt and .pronsolerc"
msgstr "" msgstr ""
#: pronterface.py:136 #: pronterface.py:149
msgid "Ignoring custombtn.txt. Remove all current buttons to revert to custombtn.txt" msgid "Ignoring custombtn.txt. Remove all current buttons to revert to custombtn.txt"
msgstr "" msgstr ""
#: pronterface.py:165 pronterface.py:520 pronterface.py:1343 #: pronterface.py:181
#: pronterface.py:1397 pronterface.py:1521 pronterface.py:1555 msgid "Failed to start web interface"
#: pronterface.py:1567 msgstr ""
#: pronterface.py:185
msgid "CherryPy is not installed. Web Interface Disabled."
msgstr ""
#: pronterface.py:197 pronterface.py:603 pronterface.py:1525
#: pronterface.py:1578 pronterface.py:1705 pronterface.py:1765
#: pronterface.py:1778
msgid "Print" msgid "Print"
msgstr "" msgstr ""
#: pronterface.py:169 #: pronterface.py:207
msgid "Printer is now online." msgid "Printer is now online."
msgstr "" msgstr ""
#: pronterface.py:170 #: pronterface.py:208
msgid "Disconnect" msgid "Disconnect"
msgstr "" msgstr ""
#: pronterface.py:229 #: pronterface.py:331
msgid "Setting hotend temperature to %f degrees Celsius." msgid "Setting hotend temperature to %f degrees Celsius."
msgstr "" msgstr ""
#: pronterface.py:248 pronterface.py:284 pronterface.py:346 #: pronterface.py:334 pronterface.py:356 pronterface.py:428
msgid "Printer is not online." msgid "Printer is not online."
msgstr "" msgstr ""
#: pronterface.py:250 #: pronterface.py:336
msgid "You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0." msgid "You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0."
msgstr "" msgstr ""
#: pronterface.py:252 #: pronterface.py:338 pronterface.py:364
msgid "You must enter a temperature. (%s)" msgid "You must enter a temperature. (%s)"
msgstr "" msgstr ""
#: pronterface.py:265 #: pronterface.py:353
msgid "Setting bed temperature to %f degrees Celsius." msgid "Setting bed temperature to %f degrees Celsius."
msgstr "" msgstr ""
#: pronterface.py:286 #: pronterface.py:360
msgid "You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0." msgid "You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0."
msgstr "" msgstr ""
#: pronterface.py:288 #: pronterface.py:381
msgid "You must enter a temperature."
msgstr ""
#: pronterface.py:303
msgid "Do you want to erase the macro?" msgid "Do you want to erase the macro?"
msgstr "" msgstr ""
#: pronterface.py:307 #: pronterface.py:385
msgid "Cancelled." msgid "Cancelled."
msgstr "" msgstr ""
#: pronterface.py:352 #: pronterface.py:436
msgid " Opens file" msgid " Opens file"
msgstr "" msgstr ""
#: pronterface.py:352 #: pronterface.py:436
msgid "&Open..." msgid "&Open..."
msgstr "" msgstr ""
#: pronterface.py:353 #: pronterface.py:437
msgid " Edit open file" msgid " Edit open file"
msgstr "" msgstr ""
#: pronterface.py:353 #: pronterface.py:437
msgid "&Edit..." msgid "&Edit..."
msgstr "" msgstr ""
#: pronterface.py:354 #: pronterface.py:438
msgid " Clear output console" msgid " Clear output console"
msgstr "" msgstr ""
#: pronterface.py:354 #: pronterface.py:438
msgid "Clear console" msgid "Clear console"
msgstr "" msgstr ""
#: pronterface.py:355 #: pronterface.py:439
msgid " Project slices" msgid " Project slices"
msgstr "" msgstr ""
#: pronterface.py:355 #: pronterface.py:439
msgid "Projector" msgid "Projector"
msgstr "" msgstr ""
#: pronterface.py:356 #: pronterface.py:440
msgid " Closes the Window" msgid " Closes the Window"
msgstr "" msgstr ""
#: pronterface.py:356 #: pronterface.py:440
msgid "E&xit" msgid "E&xit"
msgstr "" msgstr ""
#: pronterface.py:357 #: pronterface.py:441
msgid "&File" msgid "&File"
msgstr "" msgstr ""
#: pronterface.py:362 #: pronterface.py:446
msgid "&Macros" msgid "&Macros"
msgstr "" msgstr ""
#: pronterface.py:363 #: pronterface.py:447
msgid "<&New...>" msgid "<&New...>"
msgstr "" msgstr ""
#: pronterface.py:364 #: pronterface.py:448
msgid " Options dialog" msgid " Options dialog"
msgstr "" msgstr ""
#: pronterface.py:364 #: pronterface.py:448
msgid "&Options" msgid "&Options"
msgstr "" msgstr ""
#: pronterface.py:366 #: pronterface.py:450
msgid " Adjust slicing settings" msgid " Adjust slicing settings"
msgstr "" msgstr ""
#: pronterface.py:366 #: pronterface.py:450
msgid "Slicing Settings" msgid "Slicing Settings"
msgstr "" msgstr ""
#: pronterface.py:373 #: pronterface.py:452
msgid "&Settings" msgid "&Settings"
msgstr "" msgstr ""
#: pronterface.py:389 #: pronterface.py:467
msgid "Enter macro name" msgid "Enter macro name"
msgstr "" msgstr ""
#: pronterface.py:392 #: pronterface.py:470
msgid "Macro name:" msgid "Macro name:"
msgstr "" msgstr ""
#: pronterface.py:395 #: pronterface.py:473
msgid "Ok" msgid "Ok"
msgstr "" msgstr ""
#: pronterface.py:399 pronterface.py:1354 pronterface.py:1613 #: pronterface.py:495
msgid "Cancel" msgid "Macro name may contain only ASCII alphanumeric symbols and underscores"
msgstr "" msgstr ""
#: pronterface.py:417 #: pronterface.py:500
msgid "Name '%s' is being used by built-in command" msgid "Name '%s' is being used by built-in command"
msgstr "" msgstr ""
#: pronterface.py:420 #: pronterface.py:548
msgid "Macro name may contain only alphanumeric symbols and underscores"
msgstr ""
#: pronterface.py:469
msgid "Port" msgid "Port"
msgstr "" msgstr ""
#: pronterface.py:488 #: pronterface.py:570 pronterface.py:1747
msgid "Connect" msgid "Connect"
msgstr "" msgstr ""
#: pronterface.py:490 #: pronterface.py:574
msgid "Connect to the printer"
msgstr ""
#: pronterface.py:492
msgid "Reset" msgid "Reset"
msgstr "" msgstr ""
#: pronterface.py:495 pronterface.py:772 #: pronterface.py:589
msgid "Mini mode"
msgstr ""
#: pronterface.py:499
msgid "Monitor Printer"
msgstr ""
#: pronterface.py:509
msgid "Load file" msgid "Load file"
msgstr "" msgstr ""
#: pronterface.py:512 #: pronterface.py:593
msgid "Compose" msgid "Compose"
msgstr "" msgstr ""
#: pronterface.py:516 #: pronterface.py:598
msgid "SD" msgid "SD"
msgstr "" msgstr ""
#: pronterface.py:524 pronterface.py:1398 pronterface.py:1444 #: pronterface.py:608 pronterface.py:1579 pronterface.py:1631
#: pronterface.py:1495 pronterface.py:1520 pronterface.py:1554 #: pronterface.py:1681 pronterface.py:1704 pronterface.py:1764
#: pronterface.py:1570 #: pronterface.py:1781
msgid "Pause" msgid "Pause"
msgstr "" msgstr ""
#: pronterface.py:537 #: pronterface.py:612
msgid "Send" msgid "Recover"
msgstr "" msgstr ""
#: pronterface.py:545 pronterface.py:646 #: pronterface.py:630
msgid "mm/min" msgid "Send"
msgstr "" msgstr ""
#: pronterface.py:547 #: pronterface.py:671
msgid "XY:" msgid "XY:"
msgstr "" msgstr ""
#: pronterface.py:549 #: pronterface.py:673
msgid "Z:" msgid "mm/min Z:"
msgstr ""
#: pronterface.py:678
msgid "Watch"
msgstr "" msgstr ""
#: pronterface.py:572 pronterface.py:653 #: pronterface.py:683
msgid "Heater:" msgid "Heat:"
msgstr "" msgstr ""
#: pronterface.py:575 pronterface.py:595 #: pronterface.py:686 pronterface.py:709
msgid "Off" msgid "Off"
msgstr "" msgstr ""
#: pronterface.py:587 pronterface.py:607 #: pronterface.py:700 pronterface.py:723
msgid "Set" msgid "Set"
msgstr "" msgstr ""
#: pronterface.py:592 pronterface.py:655 #: pronterface.py:706
msgid "Bed:" msgid "Bed:"
msgstr "" msgstr ""
#: pronterface.py:640 #: pronterface.py:756
msgid "mm" msgid "mm"
msgstr "" msgstr ""
#: pronterface.py:698 pronterface.py:1206 pronterface.py:1438 #: pronterface.py:764
msgid ""
"mm/\n"
"min"
msgstr ""
#: pronterface.py:821 pronterface.py:1387 pronterface.py:1625
#: pronterface.py:1723
msgid "Not connected to printer." msgid "Not connected to printer."
msgstr "" msgstr ""
#: pronterface.py:727 #: pronterface.py:869
msgid "SD Upload" msgid "SD Upload"
msgstr "" msgstr ""
#: pronterface.py:731 #: pronterface.py:873
msgid "SD Print" msgid "SD Print"
msgstr "" msgstr ""
#: pronterface.py:779 #: pronterface.py:914
msgid "Mini mode"
msgstr ""
#: pronterface.py:921
msgid "Full mode" msgid "Full mode"
msgstr "" msgstr ""
#: pronterface.py:804 #: pronterface.py:946
msgid "Execute command: " msgid "Execute command: "
msgstr "" msgstr ""
#: pronterface.py:815 #: pronterface.py:957
msgid "click to add new custom button" msgid "click to add new custom button"
msgstr "" msgstr ""
#: pronterface.py:834 #: pronterface.py:979
msgid "Defines custom button. Usage: button <num> \"title\" [/c \"colour\"] command" msgid "Defines custom button. Usage: button <num> \"title\" [/c \"colour\"] command"
msgstr "" msgstr ""
#: pronterface.py:856 #: pronterface.py:1003
msgid "Custom button number should be between 0 and 63" msgid "Custom button number should be between 0 and 63"
msgstr "" msgstr ""
#: pronterface.py:948 #: pronterface.py:1096
msgid "Edit custom button '%s'" msgid "Edit custom button '%s'"
msgstr "" msgstr ""
#: pronterface.py:950 #: pronterface.py:1098
msgid "Move left <<" msgid "Move left <<"
msgstr "" msgstr ""
#: pronterface.py:953 #: pronterface.py:1101
msgid "Move right >>" msgid "Move right >>"
msgstr "" msgstr ""
#: pronterface.py:957 #: pronterface.py:1105
msgid "Remove custom button '%s'" msgid "Remove custom button '%s'"
msgstr "" msgstr ""
#: pronterface.py:960 #: pronterface.py:1108
msgid "Add custom button" msgid "Add custom button"
msgstr "" msgstr ""
#: pronterface.py:1105 #: pronterface.py:1270
msgid "event object missing" msgid "event object missing"
msgstr "" msgstr ""
#: pronterface.py:1133 #: pronterface.py:1306
msgid "Invalid period given." msgid "Invalid period given."
msgstr "" msgstr ""
#: pronterface.py:1136 #: pronterface.py:1311
msgid "Monitoring printer." msgid "Monitoring printer."
msgstr "" msgstr ""
#: pronterface.py:1138 #: pronterface.py:1315
msgid "Done monitoring." msgid "Done monitoring."
msgstr "" msgstr ""
#: pronterface.py:1160 #: pronterface.py:1355
msgid "Printer is online. "
msgstr ""
#: pronterface.py:1162 pronterface.py:1341
msgid "Loaded "
msgstr ""
#: pronterface.py:1165
msgid "Bed"
msgstr ""
#: pronterface.py:1165
msgid "Hotend"
msgstr ""
#: pronterface.py:1175
msgid " SD printing:%04.2f %%" msgid " SD printing:%04.2f %%"
msgstr "" msgstr ""
#: pronterface.py:1178 #: pronterface.py:1358
msgid " Printing:%04.2f %% |" msgid " Printing: %04.2f%% |"
msgstr "" msgstr ""
#: pronterface.py:1179 #: pronterface.py:1359
msgid " Line# %d of %d lines |" msgid " Line# %d of %d lines |"
msgstr "" msgstr ""
#: pronterface.py:1184 #: pronterface.py:1364
msgid " Est: %s of %s remaining | " msgid " Est: %s of %s remaining | "
msgstr "" msgstr ""
#: pronterface.py:1186 #: pronterface.py:1366
msgid " Z: %0.2f mm" msgid " Z: %0.2f mm"
msgstr "" msgstr ""
#: pronterface.py:1257 #: pronterface.py:1439
msgid "Opening file failed." msgid "Opening file failed."
msgstr "" msgstr ""
#: pronterface.py:1263 #: pronterface.py:1445
msgid "Starting print" msgid "Starting print"
msgstr "" msgstr ""
#: pronterface.py:1286 #: pronterface.py:1466
msgid "Pick SD file" msgid "Pick SD file"
msgstr "" msgstr ""
#: pronterface.py:1286 #: pronterface.py:1466
msgid "Select the file to print" msgid "Select the file to print"
msgstr "" msgstr ""
#: pronterface.py:1321 #: pronterface.py:1501
msgid "Failed to execute slicing software: " msgid "Failed to execute slicing software: "
msgstr "" msgstr ""
#: pronterface.py:1328 #: pronterface.py:1510
msgid "Slicing..." msgid "Slicing..."
msgstr "" msgstr ""
#: pronterface.py:1341 #: pronterface.py:1523
msgid ", %d lines" msgid ", %d lines"
msgstr "" msgstr ""
#: pronterface.py:1348 #: pronterface.py:1523
msgid "Loaded "
msgstr ""
#: pronterface.py:1530
msgid "Load File" msgid "Load File"
msgstr "" msgstr ""
#: pronterface.py:1355 #: pronterface.py:1536
msgid "Slicing " msgid "Slicing "
msgstr "" msgstr ""
#: pronterface.py:1374 #: pronterface.py:1555
msgid "Open file to print" msgid "Open file to print"
msgstr "" msgstr ""
#: pronterface.py:1375 #: pronterface.py:1556
msgid "OBJ, STL, and GCODE files (*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ)|*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|All Files (*.*)|*.*" msgid "OBJ, STL, and GCODE files (*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ)|*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|All Files (*.*)|*.*"
msgstr "" msgstr ""
#: pronterface.py:1382 #: pronterface.py:1563
msgid "File not found!" msgid "File not found!"
msgstr "" msgstr ""
#: pronterface.py:1396 #: pronterface.py:1577
msgid "Loaded %s, %d lines" msgid "Loaded %s, %d lines"
msgstr "" msgstr ""
#: pronterface.py:1406 #: pronterface.py:1588
msgid "" msgid ""
"mm of filament used in this print\n" "mm of filament used in this print\n"
msgstr "" msgstr ""
#: pronterface.py:1407 #: pronterface.py:1589 pronterface.py:1591
msgid "" msgid ""
"the print goes from %f mm to %f mm in X\n" "the print goes from %f mm to %f mm in X\n"
"and is %f mm wide\n" "and is %f mm wide\n"
msgstr "" msgstr ""
#: pronterface.py:1408 #: pronterface.py:1592
msgid "" msgid ""
"the print goes from %f mm to %f mm in Y\n" "the print goes from %f mm to %f mm in Y\n"
"and is %f mm wide\n" "and is %f mm wide\n"
msgstr "" msgstr ""
#: pronterface.py:1409 #: pronterface.py:1593
msgid "" msgid ""
"the print goes from %f mm to %f mm in Z\n" "the print goes from %f mm to %f mm in Z\n"
"and is %f mm high\n" "and is %f mm high\n"
msgstr "" msgstr ""
#: pronterface.py:1410 #: pronterface.py:1595
msgid "Estimated duration (pessimistic): " msgid "Estimated duration (pessimistic): "
msgstr "" msgstr ""
#: pronterface.py:1435 #: pronterface.py:1622
msgid "No file loaded. Please use load first." msgid "No file loaded. Please use load first."
msgstr "" msgstr ""
#: pronterface.py:1446 #: pronterface.py:1633
msgid "Restart" msgid "Restart"
msgstr "" msgstr ""
#: pronterface.py:1450 #: pronterface.py:1637
msgid "File upload complete" msgid "File upload complete"
msgstr "" msgstr ""
#: pronterface.py:1469 #: pronterface.py:1656
msgid "Pick SD filename" msgid "Pick SD filename"
msgstr "" msgstr ""
#: pronterface.py:1477 #: pronterface.py:1663
msgid "Paused." msgid "Paused."
msgstr "" msgstr ""
#: pronterface.py:1488 #: pronterface.py:1674
msgid "Resume" msgid "Resume"
msgstr "" msgstr ""
#: pronterface.py:1504 #: pronterface.py:1688
msgid "Connecting..." msgid "Connecting..."
msgstr "" msgstr ""
#: pronterface.py:1535 #: pronterface.py:1738
msgid "Disconnected." msgid "Disconnected."
msgstr "" msgstr ""
#: pronterface.py:1562 #: pronterface.py:1771
msgid "Reset." msgid "Reset."
msgstr "" msgstr ""
#: pronterface.py:1563 #: pronterface.py:1772
msgid "Are you sure you want to reset the printer?" msgid "Are you sure you want to reset the printer?"
msgstr "" msgstr ""
#: pronterface.py:1563 #: pronterface.py:1772
msgid "Reset?" msgid "Reset?"
msgstr "" msgstr ""
#: pronterface.py:1609
msgid "Save"
msgstr ""
#: pronterface.py:1665
msgid "Edit settings"
msgstr ""
#: pronterface.py:1667
msgid "Defaults"
msgstr ""
#: pronterface.py:1696
msgid "Custom button"
msgstr ""
#: pronterface.py:1701
msgid "Button title"
msgstr ""
#: pronterface.py:1704
msgid "Command"
msgstr ""
#: pronterface.py:1713
msgid "Color"
msgstr ""
#!/usr/bin/env python #!/usr/bin/env python
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -46,7 +46,7 @@ def evalme(s): ...@@ -46,7 +46,7 @@ def evalme(s):
class stlwrap: class stlwrap:
def __init__(self, obj, name=None): def __init__(self, obj, name = None):
self.obj = obj self.obj = obj
self.name = name self.name = name
if name is None: if name is None:
...@@ -58,7 +58,7 @@ class stlwrap: ...@@ -58,7 +58,7 @@ class stlwrap:
class showstl(wx.Window): class showstl(wx.Window):
def __init__(self, parent, size, pos): def __init__(self, parent, size, pos):
wx.Window.__init__(self, parent, size=size, pos=pos) wx.Window.__init__(self, parent, size = size, pos = pos)
#self.SetBackgroundColour((0, 0, 0)) #self.SetBackgroundColour((0, 0, 0))
#wx.FutureCall(200, self.paint) #wx.FutureCall(200, self.paint)
self.i = 0 self.i = 0
...@@ -141,7 +141,7 @@ class showstl(wx.Window): ...@@ -141,7 +141,7 @@ class showstl(wx.Window):
self.i += angle self.i += angle
if not self.triggered: if not self.triggered:
self.triggered = 1 self.triggered = 1
threading.Thread(target=self.cr).start() threading.Thread(target = self.cr).start()
def keypress(self, event): def keypress(self, event):
"""gets keypress events and moves/rotates acive shape""" """gets keypress events and moves/rotates acive shape"""
...@@ -200,9 +200,9 @@ class showstl(wx.Window): ...@@ -200,9 +200,9 @@ class showstl(wx.Window):
def repaint(self, event): def repaint(self, event):
dc = wx.PaintDC(self) dc = wx.PaintDC(self)
self.paint(dc=dc) self.paint(dc = dc)
def paint(self, coord1="x", coord2="y", dc=None): def paint(self, coord1 = "x", coord2 = "y", dc = None):
coords = {"x": 0, "y": 1, "z": 2} coords = {"x": 0, "y": 1, "z": 2}
if dc is None: if dc is None:
dc = wx.ClientDC(self) dc = wx.ClientDC(self)
...@@ -231,7 +231,7 @@ class showstl(wx.Window): ...@@ -231,7 +231,7 @@ class showstl(wx.Window):
bm = wx.BitmapFromImage(im) bm = wx.BitmapFromImage(im)
dcs.SelectObject(bm) dcs.SelectObject(bm)
bsz = bm.GetSize() bsz = bm.GetSize()
dc.Blit(scale * m.offsets[0] - bsz[0] / 2, 400 - (scale * m.offsets[1] + bsz[1] / 2), bsz[0], bsz[1], dcs, 0, 0, useMask=1) dc.Blit(scale * m.offsets[0] - bsz[0] / 2, 400 - (scale * m.offsets[1] + bsz[1] / 2), bsz[0], bsz[1], dcs, 0, 0, useMask = 1)
#for i in m.facets:#random.sample(m.facets, min(100000, len(m.facets))): #for i in m.facets:#random.sample(m.facets, min(100000, len(m.facets))):
# dc.DrawPolygon([wx.Point(offset[0]+scale*m.offsets[0]+scale*p[0], 400-(offset[1]+scale*m.offsets[1]+scale*p[1])) for p in i[1]]) # dc.DrawPolygon([wx.Point(offset[0]+scale*m.offsets[0]+scale*p[0], 400-(offset[1]+scale*m.offsets[1]+scale*p[1])) for p in i[1]])
#if(time.time()-t)>5: #if(time.time()-t)>5:
...@@ -242,29 +242,29 @@ class showstl(wx.Window): ...@@ -242,29 +242,29 @@ class showstl(wx.Window):
class stlwin(wx.Frame): class stlwin(wx.Frame):
def __init__(self, size=(800, 580), callback=None, parent=None): def __init__(self, size = (800, 580), callback = None, parent = None):
wx.Frame.__init__(self, parent, title=_("Plate building tool"), size=size) wx.Frame.__init__(self, parent, title = _("Plate building tool"), size = size)
self.SetIcon(wx.Icon(pixmapfile("plater.ico"), wx.BITMAP_TYPE_ICO)) self.SetIcon(wx.Icon(pixmapfile("plater.ico"), wx.BITMAP_TYPE_ICO))
self.mainsizer = wx.BoxSizer(wx.HORIZONTAL) self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
self.panel = wx.Panel(self, -1, size=(150, 600), pos=(0, 0)) self.panel = wx.Panel(self, -1, size = (150, 600), pos = (0, 0))
#self.panel.SetBackgroundColour((10, 10, 10)) #self.panel.SetBackgroundColour((10, 10, 10))
self.l = wx.ListBox(self.panel, size=(300, 180), pos=(0, 30)) self.l = wx.ListBox(self.panel, size = (300, 180), pos = (0, 30))
self.cl = wx.Button(self.panel, label=_("Clear"), pos=(0, 205)) self.cl = wx.Button(self.panel, label = _("Clear"), pos = (0, 205))
self.lb = wx.Button(self.panel, label=_("Load"), pos=(0, 0)) self.lb = wx.Button(self.panel, label = _("Load"), pos = (0, 0))
if(callback is None): if(callback is None):
self.eb = wx.Button(self.panel, label=_("Export"), pos=(100, 0)) self.eb = wx.Button(self.panel, label = _("Export"), pos = (100, 0))
self.eb.Bind(wx.EVT_BUTTON, self.export) self.eb.Bind(wx.EVT_BUTTON, self.export)
else: else:
self.eb = wx.Button(self.panel, label=_("Export"), pos=(200, 205)) self.eb = wx.Button(self.panel, label = _("Export"), pos = (200, 205))
self.eb.Bind(wx.EVT_BUTTON, self.export) self.eb.Bind(wx.EVT_BUTTON, self.export)
self.edb = wx.Button(self.panel, label=_("Done"), pos=(100, 0)) self.edb = wx.Button(self.panel, label = _("Done"), pos = (100, 0))
self.edb.Bind(wx.EVT_BUTTON, lambda e: self.done(e, callback)) self.edb.Bind(wx.EVT_BUTTON, lambda e: self.done(e, callback))
self.eb = wx.Button(self.panel, label=_("Cancel"), pos=(200, 0)) self.eb = wx.Button(self.panel, label = _("Cancel"), pos = (200, 0))
self.eb.Bind(wx.EVT_BUTTON, lambda e: self.Destroy()) self.eb.Bind(wx.EVT_BUTTON, lambda e: self.Destroy())
self.sb = wx.Button(self.panel, label=_("Snap to Z = 0"), pos=(00, 255)) self.sb = wx.Button(self.panel, label = _("Snap to Z = 0"), pos = (00, 255))
self.cb = wx.Button(self.panel, label=_("Put at 100, 100"), pos=(0, 280)) self.cb = wx.Button(self.panel, label = _("Put at 100, 100"), pos = (0, 280))
self.db = wx.Button(self.panel, label=_("Delete"), pos=(0, 305)) self.db = wx.Button(self.panel, label = _("Delete"), pos = (0, 305))
self.ab = wx.Button(self.panel, label=_("Auto"), pos=(0, 330)) self.ab = wx.Button(self.panel, label = _("Auto"), pos = (0, 330))
self.cl.Bind(wx.EVT_BUTTON, self.clear) self.cl.Bind(wx.EVT_BUTTON, self.clear)
self.lb.Bind(wx.EVT_BUTTON, self.right) self.lb.Bind(wx.EVT_BUTTON, self.right)
self.sb.Bind(wx.EVT_BUTTON, self.snap) self.sb.Bind(wx.EVT_BUTTON, self.snap)
...@@ -336,25 +336,25 @@ class stlwin(wx.Frame): ...@@ -336,25 +336,25 @@ class stlwin(wx.Frame):
def center(self, event): def center(self, event):
i = self.l.GetSelection() i = self.l.GetSelection()
if i != -1: if i != -1:
m = self.models[self.l.GetString(i)] m = self.models[self.l.GetString(i)]
m.offsets = [100, 100, m.offsets[2]] m.offsets = [100, 100, m.offsets[2]]
self.Refresh() self.Refresh()
def snap(self, event): def snap(self, event):
i = self.l.GetSelection() i = self.l.GetSelection()
if i != -1: if i != -1:
m = self.models[self.l.GetString(i)] m = self.models[self.l.GetString(i)]
m.offsets[2] = -1.0 * min(m.facetsminz)[0] m.offsets[2] = -1.0 * min(m.facetsminz)[0]
#print m.offsets[2] #print m.offsets[2]
self.Refresh() self.Refresh()
def delete(self, event): def delete(self, event):
i = self.l.GetSelection() i = self.l.GetSelection()
if i != -1: if i != -1:
del self.models[self.l.GetString(i)] del self.models[self.l.GetString(i)]
self.l.Delete(i) self.l.Delete(i)
self.l.Select(self.l.GetCount() - 1) self.l.Select(self.l.GetCount() - 1)
self.Refresh() self.Refresh()
def done(self, event, cb): def done(self, event, cb):
try: try:
...@@ -368,7 +368,7 @@ class stlwin(wx.Frame): ...@@ -368,7 +368,7 @@ class stlwin(wx.Frame):
self.Destroy() self.Destroy()
def export(self, event): def export(self, event):
dlg = wx.FileDialog(self, _("Pick file to save to"), self.basedir, style=wx.FD_SAVE) dlg = wx.FileDialog(self, _("Pick file to save to"), self.basedir, style = wx.FD_SAVE)
dlg.SetWildcard(_("STL files (;*.stl;*.STL;)")) dlg.SetWildcard(_("STL files (;*.stl;*.STL;)"))
if(dlg.ShowModal() == wx.ID_OK): if(dlg.ShowModal() == wx.ID_OK):
name = dlg.GetPath() name = dlg.GetPath()
...@@ -393,7 +393,7 @@ class stlwin(wx.Frame): ...@@ -393,7 +393,7 @@ class stlwin(wx.Frame):
print _("wrote %s") % name print _("wrote %s") % name
def right(self, event): def right(self, event):
dlg = wx.FileDialog(self, _("Pick file to load"), self.basedir, style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) dlg = wx.FileDialog(self, _("Pick file to load"), self.basedir, style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
dlg.SetWildcard(_("STL files (;*.stl;*.STL;)|*.stl|OpenSCAD files (;*.scad;)|*.scad")) dlg.SetWildcard(_("STL files (;*.stl;*.STL;)|*.stl|OpenSCAD files (;*.scad;)|*.scad"))
if(dlg.ShowModal() == wx.ID_OK): if(dlg.ShowModal() == wx.ID_OK):
name = dlg.GetPath() name = dlg.GetPath()
...@@ -443,7 +443,7 @@ class stlwin(wx.Frame): ...@@ -443,7 +443,7 @@ class stlwin(wx.Frame):
self.Refresh() self.Refresh()
#print time.time()-t #print time.time()-t
def load_stl_into_model(self, path, name, offset=[0, 0, 0], rotation=0, scale=[1.0, 1.0, 1.0]): def load_stl_into_model(self, path, name, offset = [0, 0, 0], rotation = 0, scale = [1.0, 1.0, 1.0]):
newname = os.path.split(name.lower())[1] newname = os.path.split(name.lower())[1]
c = 1 c = 1
while newname in self.models: while newname in self.models:
......
#!/usr/bin/env python #!/usr/bin/env python
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -19,301 +19,327 @@ from serial import Serial, SerialException ...@@ -19,301 +19,327 @@ from serial import Serial, SerialException
from threading import Thread from threading import Thread
from select import error as SelectError from select import error as SelectError
import time, getopt, sys import time, getopt, sys
import platform, os
def control_ttyhup(port, disable_hup):
"""Controls the HUPCL"""
if platform.system() == "Linux":
if disable_hup:
os.system("stty -F %s -hup" % port)
else:
os.system("stty -F %s hup" % port)
def enable_hup(port):
control_ttyhup(port, False)
def disable_hup(port):
control_ttyhup(port, True)
class printcore(): class printcore():
def __init__(self,port=None,baud=None): def __init__(self, port = None, baud = None):
"""Initializes a printcore instance. Pass the port and baud rate to connect immediately """Initializes a printcore instance. Pass the port and baud rate to connect immediately
""" """
self.baud=None self.baud = None
self.port=None self.port = None
self.printer=None #Serial instance connected to the printer, None when disconnected self.printer = None #Serial instance connected to the printer, None when disconnected
self.clear=0 #clear to send, enabled after responses self.clear = 0 #clear to send, enabled after responses
self.online=False #The printer has responded to the initial command and is active self.online = False #The printer has responded to the initial command and is active
self.printing=False #is a print currently running, true if printing, false if paused self.printing = False #is a print currently running, true if printing, false if paused
self.mainqueue=[] self.mainqueue = []
self.priqueue=[] self.priqueue = []
self.queueindex=0 self.queueindex = 0
self.lineno=0 self.lineno = 0
self.resendfrom=-1 self.resendfrom = -1
self.paused=False self.paused = False
self.sentlines={} self.sentlines = {}
self.log=[] self.log = []
self.sent=[] self.sent = []
self.tempcb=None#impl (wholeline) self.tempcb = None #impl (wholeline)
self.recvcb=None#impl (wholeline) self.recvcb = None #impl (wholeline)
self.sendcb=None#impl (wholeline) self.sendcb = None #impl (wholeline)
self.errorcb=None#impl (wholeline) self.errorcb = None #impl (wholeline)
self.startcb=None#impl () self.startcb = None #impl ()
self.endcb=None#impl () self.endcb = None #impl ()
self.onlinecb=None#impl () self.onlinecb = None #impl ()
self.loud=False#emit sent and received lines to terminal self.loud = False #emit sent and received lines to terminal
self.greetings=['start','Grbl '] self.greetings = ['start','Grbl ']
self.wait=0# default wait period for send(), send_now() self.wait = 0 # default wait period for send(), send_now()
self.read_thread = None
self.stop_read_thread = False
self.print_thread = None
if port is not None and baud is not None: if port is not None and baud is not None:
#print port, baud
self.connect(port, baud) self.connect(port, baud)
#print "connected\n"
def disconnect(self): def disconnect(self):
"""Disconnects from printer and pauses the print """Disconnects from printer and pauses the print
""" """
if(self.printer): if self.printer:
if self.read_thread:
self.stop_read_thread = True
self.read_thread.join()
self.read_thread = None
self.printer.close() self.printer.close()
self.printer=None self.printer = None
self.online=False self.online = False
self.printing=False self.printing = False
def connect(self,port=None,baud=None): def connect(self, port = None, baud = None):
"""Set port and baudrate if given, then connect to printer """Set port and baudrate if given, then connect to printer
""" """
if(self.printer): if self.printer:
self.disconnect() self.disconnect()
if port is not None: if port is not None:
self.port=port self.port = port
if baud is not None: if baud is not None:
self.baud=baud self.baud = baud
if self.port is not None and self.baud is not None: if self.port is not None and self.baud is not None:
self.printer=Serial(self.port,self.baud,timeout=5) disable_hup(self.port)
Thread(target=self._listen).start() self.printer = Serial(port = self.port, baudrate = self.baud, timeout = 0.25)
self.stop_read_thread = False
self.read_thread = Thread(target = self._listen)
self.read_thread.start()
def reset(self): def reset(self):
"""Reset the printer """Reset the printer
""" """
if(self.printer): if self.printer:
self.printer.setDTR(1) self.printer.setDTR(1)
time.sleep(0.2)
self.printer.setDTR(0) self.printer.setDTR(0)
def _readline(self):
try:
line = self.printer.readline()
if len(line) > 1:
self.log.append(line)
if self.recvcb:
try: self.recvcb(line)
except: pass
if self.loud: print "RECV: ", line.rstrip()
return line
except SelectError, e:
if 'Bad file descriptor' in e.args[1]:
print "Can't read from printer (disconnected?)."
return None
else:
raise
except SerialException, e:
print "Can't read from printer (disconnected?)."
return None
except OSError, e:
print "Can't read from printer (disconnected?)."
return None
def _listen_can_continue(self):
return not self.stop_read_thread and self.printer and self.printer.isOpen()
def _listen_until_online(self):
while not self.online and self._listen_can_continue():
self._send("M105")
empty_lines = 0
while self._listen_can_continue():
line = self._readline()
if line == None: break # connection problem
# workaround cases where M105 was sent before printer Serial
# was online an empty line means read timeout was reached,
# meaning no data was received thus we count those empty lines,
# and once we have seen 5 in a row, we just break and send a
# new M105
if not line: empty_lines += 1
else: empty_lines = 0
if empty_lines == 5: break
if line.startswith(tuple(self.greetings)) or line.startswith('ok'):
if self.onlinecb:
try: self.onlinecb()
except: pass
self.online = True
return
time.sleep(0.25)
def _listen(self): def _listen(self):
"""This function acts on messages from the firmware """This function acts on messages from the firmware
""" """
self.clear=True self.clear = True
time.sleep(1.0) if not self.printing:
if (not self.online and not self.printing): self._listen_until_online()
self._send("M105") while self._listen_can_continue():
while(True): line = self._readline()
if(not self.printer or not self.printer.isOpen): if line == None:
break break
try: if line.startswith('DEBUG_'):
line=self.printer.readline()
except SelectError, e:
if 'Bad file descriptor' in e.args[1]:
print "Can't read from printer (disconnected?)."
break
else:
raise
except SerialException, e:
print "Can't read from printer (disconnected?)."
break
except OSError, e:
print "Can't read from printer (disconnected?)."
break
if(len(line)>1):
self.log+=[line]
if self.recvcb is not None:
try:
self.recvcb(line)
except:
pass
if self.loud:
print "RECV: ",line.rstrip()
if(line.startswith('DEBUG_')):
continue continue
if(line.startswith(tuple(self.greetings)) or line.startswith('ok')): if line.startswith(tuple(self.greetings)) or line.startswith('ok'):
self.clear=True self.clear = True
if(line.startswith(tuple(self.greetings)) or line.startswith('ok') or "T:" in line): if line.startswith('ok') and "T:" in line and self.tempcb:
if (not self.online or line.startswith(tuple(self.greetings))) and self.onlinecb is not None:
try:
self.onlinecb()
except:
pass
self.online=True
if(line.startswith('ok')):
#self.resendfrom=-1
#put temp handling here
if "T:" in line and self.tempcb is not None:
try:
self.tempcb(line)
except:
pass
#callback for temp, status, whatever #callback for temp, status, whatever
elif(line.startswith('Error')): try: self.tempcb(line)
if self.errorcb is not None: except: pass
try: elif line.startswith('Error'):
self.errorcb(line) if self.errorcb:
except:
pass
#callback for errors #callback for errors
pass try: self.errorcb(line)
except: pass
# Teststrings for resend parsing # Firmware exp. result # Teststrings for resend parsing # Firmware exp. result
# line="rs N2 Expected checksum 67" # Teacup 2 # line="rs N2 Expected checksum 67" # Teacup 2
if line.lower().startswith("resend") or line.startswith("rs"): if line.lower().startswith("resend") or line.startswith("rs"):
line=line.replace("N:"," ").replace("N"," ").replace(":"," ") line = line.replace("N:"," ").replace("N"," ").replace(":"," ")
linewords=line.split() linewords = line.split()
while len(linewords) != 0: while len(linewords) != 0:
try: try:
toresend=int(linewords.pop(0)) toresend = int(linewords.pop(0))
self.resendfrom=toresend self.resendfrom = toresend
#print str(toresend) #print str(toresend)
break break
except: except:
pass pass
self.clear=True self.clear = True
self.clear=True self.clear = True
#callback for disconnect
def _checksum(self, command):
def _checksum(self,command): return reduce(lambda x, y:x^y, map(ord, command))
return reduce(lambda x,y:x^y, map(ord,command))
def startprint(self, data, startindex = 0):
def startprint(self,data):
"""Start a print, data is an array of gcode commands. """Start a print, data is an array of gcode commands.
returns True on success, False if already printing. returns True on success, False if already printing.
The print queue will be replaced with the contents of the data array, the next line will be set to 0 and the firmware notified. The print queue will be replaced with the contents of the data array, the next line will be set to 0 and the firmware notified.
Printing will then start in a parallel thread. Printing will then start in a parallel thread.
""" """
if(self.printing or not self.online or not self.printer): if self.printing or not self.online or not self.printer:
return False return False
self.printing=True self.printing = True
self.mainqueue=[]+data self.mainqueue = [] + data
self.lineno=0 self.lineno = 0
self.queueindex=0 self.queueindex = startindex
self.resendfrom=-1 self.resendfrom = -1
self._send("M110",-1, True) self._send("M110", -1, True)
if len(data)==0: if len(data) == 0:
return True return True
self.clear=False self.clear = False
Thread(target=self._print).start() self.print_thread = Thread(target = self._print)
self.print_thread.start()
return True return True
def pause(self): def pause(self):
"""Pauses the print, saving the current position. """Pauses the print, saving the current position.
""" """
self.paused=True self.paused = True
self.printing=False self.printing = False
time.sleep(1) self.print_thread.join()
self.print_thread = None
def resume(self): def resume(self):
"""Resumes a paused print. """Resumes a paused print.
""" """
self.paused=False self.paused = False
self.printing=True self.printing = True
Thread(target=self._print).start() self.print_thread = Thread(target = self._print)
self.print_thread.start()
def send(self,command,wait=0):
def send(self, command, wait = 0):
"""Adds a command to the checksummed main command queue if printing, or sends the command immediately if not printing """Adds a command to the checksummed main command queue if printing, or sends the command immediately if not printing
""" """
if(self.online): if self.online:
if(self.printing): if self.printing:
self.mainqueue+=[command] self.mainqueue.append(command)
else: else:
while not self.clear: while self.printer and self.printing and not self.clear:
time.sleep(0.001) time.sleep(0.001)
if (wait == 0 and self.wait > 0): if wait == 0 and self.wait > 0:
wait = self.wait wait = self.wait
if (wait > 0): if wait > 0:
self.clear=False self.clear = False
self._send(command,self.lineno,True) self._send(command, self.lineno, True)
self.lineno+=1 self.lineno += 1
while ((wait > 0) and not self.clear): while wait > 0 and self.printer and self.printing and not self.clear:
time.sleep(0.001) time.sleep(0.001)
wait-=1 wait -= 1
else: else:
print "Not connected to printer." print "Not connected to printer."
def send_now(self, command, wait = 0):
def send_now(self,command,wait=0):
"""Sends a command to the printer ahead of the command queue, without a checksum """Sends a command to the printer ahead of the command queue, without a checksum
""" """
if(self.online or force): if self.online or force:
if(self.printing): if self.printing:
self.priqueue+=[command] self.priqueue.append(command)
else: else:
while not self.clear: while self.printer and self.printing and not self.clear:
time.sleep(0.001) time.sleep(0.001)
if (wait == 0 and self.wait > 0): if wait == 0 and self.wait > 0:
wait = self.wait wait = self.wait
if (wait > 0): if wait > 0:
self.clear=False self.clear = False
self._send(command) self._send(command)
while ((wait > 0) and not self.clear): while (wait > 0) and self.printer and self.printing and not self.clear:
time.sleep(0.001) time.sleep(0.001)
wait-=1 wait -= 1
#callback for command sent
else: else:
print "Not connected to printer." print "Not connected to printer."
def _print(self): def _print(self):
#callback for printing started if self.startcb:
if self.startcb is not None: #callback for printing started
try: try: self.startcb()
self.startcb() except: pass
except: while self.printing and self.printer and self.online:
pass
while(self.printing and self.printer and self.online):
self._sendnext() self._sendnext()
self.sentlines={} self.sentlines = {}
self.log=[] self.log = []
self.sent=[] self.sent = []
if self.endcb is not None: if self.endcb:
try: #callback for printing done
self.endcb() try: self.endcb()
except: except: pass
pass
#callback for printing done
def _sendnext(self): def _sendnext(self):
if(not self.printer): if not self.printer:
return return
while not self.clear: while self.printer and self.printing and not self.clear:
time.sleep(0.001) time.sleep(0.001)
self.clear=False self.clear = False
if not (self.printing and self.printer and self.online): if not (self.printing and self.printer and self.online):
self.clear=True self.clear = True
return return
if(self.resendfrom<self.lineno and self.resendfrom>-1): if self.resendfrom < self.lineno and self.resendfrom > -1:
self._send(self.sentlines[self.resendfrom],self.resendfrom,False) self._send(self.sentlines[self.resendfrom], self.resendfrom, False)
self.resendfrom+=1 self.resendfrom += 1
return return
self.resendfrom=-1 self.resendfrom = -1
for i in self.priqueue[:]: for i in self.priqueue[:]:
self._send(i) self._send(i)
del(self.priqueue[0]) del self.priqueue[0]
return return
if(self.printing and self.queueindex<len(self.mainqueue)): if self.printing and self.queueindex < len(self.mainqueue):
tline=self.mainqueue[self.queueindex] tline = self.mainqueue[self.queueindex]
tline=tline.split(";")[0] tline = tline.split(";")[0]
if(len(tline)>0): if len(tline) > 0:
self._send(tline,self.lineno,True) self._send(tline, self.lineno, True)
self.lineno+=1 self.lineno += 1
else: else:
self.clear=True self.clear = True
self.queueindex+=1 self.queueindex += 1
else: else:
self.printing=False self.printing = False
self.clear=True self.clear = True
if(not self.paused): if not self.paused:
self.queueindex=0 self.queueindex = 0
self.lineno=0 self.lineno = 0
self._send("M110",-1, True) self._send("M110", -1, True)
def _send(self, command, lineno=0, calcchecksum=False): def _send(self, command, lineno = 0, calcchecksum = False):
if(calcchecksum): if calcchecksum:
prefix="N"+str(lineno)+" "+command prefix = "N" + str(lineno) + " " + command
command=prefix+"*"+str(self._checksum(prefix)) command = prefix + "*" + str(self._checksum(prefix))
if("M110" not in command): if "M110" not in command:
self.sentlines[lineno]=command self.sentlines[lineno] = command
if(self.printer): if self.printer:
self.sent+=[command] self.sent.append(command)
if self.loud: if self.loud:
print "SENT: ",command print "SENT: ", command
if self.sendcb is not None: if self.sendcb:
try: try: self.sendcb(command)
self.sendcb(command) except: pass
except:
pass
try: try:
self.printer.write(str(command+"\n")) self.printer.write(str(command+"\n"))
except SerialException, e: except SerialException, e:
...@@ -322,48 +348,47 @@ class printcore(): ...@@ -322,48 +348,47 @@ class printcore():
if __name__ == '__main__': if __name__ == '__main__':
baud = 115200 baud = 115200
loud = False loud = False
statusreport=False statusreport = False
try: try:
opts, args=getopt.getopt(sys.argv[1:], "h,b:,v,s",["help","baud","verbose","statusreport"]) opts, args = getopt.getopt(sys.argv[1:], "h,b:,v,s",
except getopt.GetoptError,err: ["help", "baud", "verbose", "statusreport"])
print str(err) except getopt.GetoptError, err:
print help print str(err)
sys.exit(2) sys.exit(2)
for o,a in opts: for o, a in opts:
if o in ('-h', '--help'): if o in ('-h', '--help'):
# FIXME: Fix help # FIXME: Fix help
print "Opts are: --help , -b --baud = baudrate, -v --verbose, -s --statusreport" print "Opts are: --help , -b --baud = baudrate, -v --verbose, -s --statusreport"
sys.exit(1) sys.exit(1)
if o in ('-b', '--baud'): if o in ('-b', '--baud'):
baud = int(a) baud = int(a)
if o in ('-v','--verbose'): if o in ('-v','--verbose'):
loud=True loud = True
elif o in ('-s','--statusreport'): elif o in ('-s','--statusreport'):
statusreport=True statusreport = True
if len(args)>1: if len (args) > 1:
port=args[-2] port = args[-2]
filename=args[-1] filename = args[-1]
print "Printing: "+filename + " on "+port + " with baudrate "+str(baud) print "Printing: %s on %s with baudrate %d" % (filename, port, baud)
else: else:
print "Usage: python [-h|-b|-v|-s] printcore.py /dev/tty[USB|ACM]x filename.gcode" print "Usage: python [-h|-b|-v|-s] printcore.py /dev/tty[USB|ACM]x filename.gcode"
sys.exit(2) sys.exit(2)
p=printcore(port,baud) p = printcore(port, baud)
p.loud = loud p.loud = loud
time.sleep(2) time.sleep(2)
gcode=[i.replace("\n","") for i in open(filename)] gcode = [i.replace("\n", "") for i in open(filename)]
p.startprint(gcode) p.startprint(gcode)
try: try:
if statusreport: if statusreport:
p.loud=False p.loud = False
sys.stdout.write("Progress: 00.0%") sys.stdout.write("Progress: 00.0%")
sys.stdout.flush() sys.stdout.flush()
while(p.printing): while p.printing:
time.sleep(1) time.sleep(1)
if statusreport: if statusreport:
sys.stdout.write("\b\b\b\b%02.1f%%" % (100*float(p.queueindex)/len(p.mainqueue),) ) sys.stdout.write("\b\b\b\b%02.1f%%" % (100 * float(p.queueindex) / len(p.mainqueue),) )
sys.stdout.flush() sys.stdout.flush()
p.disconnect() p.disconnect()
sys.exit(0) sys.exit(0)
......
...@@ -16,13 +16,13 @@ class SkeinforgeQuickEditDialog(wx.Dialog): ...@@ -16,13 +16,13 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
self.cancelButton = wx.Button(self, wx.ID_CANCEL, "") self.cancelButton = wx.Button(self, wx.ID_CANCEL, "")
self.Bind(wx.EVT_BUTTON, self.OnExit, self.cancelButton) self.Bind(wx.EVT_BUTTON, self.OnExit, self.cancelButton)
self.Bind(wx.EVT_BUTTON, self.OnSave, self.okButton) self.Bind(wx.EVT_BUTTON, self.OnSave, self.okButton)
""" """
The following list determines which settings are shown. The following list determines which settings are shown.
The dictionary key is the plugin name and the value is a list of setting names as found in the corresponding .csv file for that plugin. The dictionary key is the plugin name and the value is a list of setting names as found in the corresponding .csv file for that plugin.
NOTE: Skeinforge is tightly integrated with Tkinter and there appears to be a dependency which stops radio-button values from being saved. NOTE: Skeinforge is tightly integrated with Tkinter and there appears to be a dependency which stops radio-button values from being saved.
Perhaps this can be solved, but at the moment this dialog cannot modify radio button values. One will have to use the main Skeinforge application. Perhaps this can be solved, but at the moment this dialog cannot modify radio button values. One will have to use the main Skeinforge application.
""" """
self.moduleSettingsMap = { self.moduleSettingsMap = {
'dimension':['Filament Diameter (mm):','Retraction Distance (millimeters):', 'Retraction Distance (millimeters):','Extruder Retraction Speed (mm/s):'], 'dimension':['Filament Diameter (mm):','Retraction Distance (millimeters):', 'Retraction Distance (millimeters):','Extruder Retraction Speed (mm/s):'],
...@@ -34,28 +34,28 @@ class SkeinforgeQuickEditDialog(wx.Dialog): ...@@ -34,28 +34,28 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
'raft':['First Layer Main Feedrate (mm/s):','First Layer Perimeter Feedrate (mm/s):','First Layer Flow Rate Infill(scaler):','First Layer Flow Rate Perimeter(scaler):',], 'raft':['First Layer Main Feedrate (mm/s):','First Layer Perimeter Feedrate (mm/s):','First Layer Flow Rate Infill(scaler):','First Layer Flow Rate Perimeter(scaler):',],
'speed':['Main Feed Rate (mm/s):','Main Flow Rate (scaler):','Perimeter Feed Rate (mm/s):','Perimeter Flow Rate (scaler):','Travel Feed Rate (mm/s):'] 'speed':['Main Feed Rate (mm/s):','Main Flow Rate (scaler):','Perimeter Feed Rate (mm/s):','Perimeter Flow Rate (scaler):','Travel Feed Rate (mm/s):']
} }
self.scrollbarPanel = wx.ScrolledWindow(self, -1, style=wx.TAB_TRAVERSAL) self.scrollbarPanel = wx.ScrolledWindow(self, -1, style = wx.TAB_TRAVERSAL)
self.settingsSizer = self.getProfileSettings() self.settingsSizer = self.getProfileSettings()
self.scrollbarPanel.SetSizer(self.settingsSizer) self.scrollbarPanel.SetSizer(self.settingsSizer)
self.__set_properties() self.__set_properties()
self.__do_layout() self.__do_layout()
self.Show() self.Show()
def __set_properties(self): def __set_properties(self):
self.profileName = skeinforge_profile.getProfileName(skeinforge_profile.getCraftTypeName()) self.profileName = skeinforge_profile.getProfileName(skeinforge_profile.getCraftTypeName())
self.SetTitle("Skeinforge Quick Edit Profile: " + self.profileName) self.SetTitle("Skeinforge Quick Edit Profile: " + self.profileName)
# For some reason the dialog size is not consistent between Windows and Linux - this is a hack to get it working # For some reason the dialog size is not consistent between Windows and Linux - this is a hack to get it working
if (os.name == 'nt'): if (os.name == 'nt'):
self.SetMinSize(wx.DLG_SZE(self, (465, 370))) self.SetMinSize(wx.DLG_SZE(self, (465, 370)))
else: else:
self.SetSize(wx.DLG_SZE(self, (465, 325))) self.SetSize(wx.DLG_SZE(self, (465, 325)))
self.SetPosition((0, 0)) self.SetPosition((0, 0))
self.scrollbarPanel.SetScrollRate(10, 10) self.scrollbarPanel.SetScrollRate(10, 10)
def __do_layout(self): def __do_layout(self):
mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer = wx.BoxSizer(wx.VERTICAL)
actionsSizer = wx.BoxSizer(wx.HORIZONTAL) actionsSizer = wx.BoxSizer(wx.HORIZONTAL)
...@@ -65,56 +65,56 @@ class SkeinforgeQuickEditDialog(wx.Dialog): ...@@ -65,56 +65,56 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
mainSizer.Add(actionsSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5) mainSizer.Add(actionsSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
self.SetSizer(mainSizer) self.SetSizer(mainSizer)
self.Layout() self.Layout()
def getProfileSettings(self): def getProfileSettings(self):
settingsSizer = wx.GridBagSizer(hgap=2, vgap=1) settingsSizer = wx.GridBagSizer(hgap = 2, vgap = 1)
settingsRow = 0 settingsRow = 0
for craftName in sorted(self.moduleSettingsMap.keys()): for craftName in sorted(self.moduleSettingsMap.keys()):
craftStaticBox = wx.StaticBox(self.scrollbarPanel, -1, craftName.capitalize()) craftStaticBox = wx.StaticBox(self.scrollbarPanel, -1, craftName.capitalize())
craftStaticBoxSizer = wx.StaticBoxSizer(craftStaticBox, wx.VERTICAL) craftStaticBoxSizer = wx.StaticBoxSizer(craftStaticBox, wx.VERTICAL)
# For some reason the dialog size is not consistent between Windows and Linux - this is a hack to get it working # For some reason the dialog size is not consistent between Windows and Linux - this is a hack to get it working
if (os.name == 'nt'): if (os.name == 'nt'):
craftStaticBoxSizer.SetMinSize((320, -1)) craftStaticBoxSizer.SetMinSize((320, -1))
else: else:
craftStaticBoxSizer.SetMinSize((450, -1)) craftStaticBoxSizer.SetMinSize((450, -1))
pluginModule = archive.getModuleWithPath(os.path.join(skeinforge_craft.getPluginsDirectoryPath(), craftName)) pluginModule = archive.getModuleWithPath(os.path.join(skeinforge_craft.getPluginsDirectoryPath(), craftName))
repo = pluginModule.getNewRepository() repo = pluginModule.getNewRepository()
for setting in settings.getReadRepository(repo).preferences: for setting in settings.getReadRepository(repo).preferences:
if setting.name in self.moduleSettingsMap[craftName]: if setting.name in self.moduleSettingsMap[craftName]:
settingSizer = wx.GridBagSizer(hgap=2, vgap=2) settingSizer = wx.GridBagSizer(hgap = 2, vgap = 2)
settingSizer.AddGrowableCol(0) settingSizer.AddGrowableCol(0)
settingRow = 0 settingRow = 0
settingLabel = wx.StaticText(self.scrollbarPanel, -1, setting.name) settingLabel = wx.StaticText(self.scrollbarPanel, -1, setting.name)
settingLabel.Wrap(400) settingLabel.Wrap(400)
settingSizer.Add(settingLabel, pos=(settingRow, 0)) settingSizer.Add(settingLabel, pos = (settingRow, 0))
if (isinstance(setting.value, bool)): if (isinstance(setting.value, bool)):
checkbox = wx.CheckBox(self.scrollbarPanel) checkbox = wx.CheckBox(self.scrollbarPanel)
checkbox.SetName(craftName + '.' + setting.name) checkbox.SetName(craftName + '.' + setting.name)
checkbox.SetValue(setting.value) checkbox.SetValue(setting.value)
settingSizer.Add(checkbox, pos=(settingRow, 1)) settingSizer.Add(checkbox, pos = (settingRow, 1))
settingSizer.AddSpacer((25, -1), pos=(settingRow, 2)) settingSizer.AddSpacer((25, -1), pos = (settingRow, 2))
else: else:
textCtrl = wx.TextCtrl(self.scrollbarPanel, value=str(setting.value), size=(50, -1)) textCtrl = wx.TextCtrl(self.scrollbarPanel, value = str(setting.value), size = (50, -1))
textCtrl.SetName(craftName + '.' + setting.name) textCtrl.SetName(craftName + '.' + setting.name)
settingSizer.Add(textCtrl, pos=(settingRow, 1)) settingSizer.Add(textCtrl, pos = (settingRow, 1))
craftStaticBoxSizer.Add(settingSizer, 1, wx.EXPAND, 0) craftStaticBoxSizer.Add(settingSizer, 1, wx.EXPAND, 0)
settingRow += 1 settingRow += 1
col = settingsRow % 2 col = settingsRow % 2
settingsSizer.Add(craftStaticBoxSizer, pos=(settingsRow - col, col)) settingsSizer.Add(craftStaticBoxSizer, pos = (settingsRow - col, col))
settingsRow += 1 settingsRow += 1
return settingsSizer return settingsSizer
def OnExit(self, e): def OnExit(self, e):
self.Destroy() self.Destroy()
def OnSave(self, e): def OnSave(self, e):
for x in self.scrollbarPanel.GetChildren(): for x in self.scrollbarPanel.GetChildren():
if (isinstance(x, (wx.CheckBox, wx.TextCtrl))): if (isinstance(x, (wx.CheckBox, wx.TextCtrl))):
......
...@@ -11,9 +11,9 @@ import shutil ...@@ -11,9 +11,9 @@ import shutil
class MyFrame(wx.Frame): class MyFrame(wx.Frame):
def __init__(self, parent, mysize): def __init__(self, parent, mysize):
wx.Frame.__init__(self, parent, wx.ID_ANY, size=mysize) wx.Frame.__init__(self, parent, wx.ID_ANY, size = mysize)
self.SetBackgroundColour('black') self.SetBackgroundColour('black')
# milliseconds per frame # milliseconds per frame
self.delay = 60 self.delay = 60
# number of loops # number of loops
...@@ -41,7 +41,7 @@ class MyFrame(wx.Frame): ...@@ -41,7 +41,7 @@ class MyFrame(wx.Frame):
self.image_list = [] self.image_list = []
for image_file in file_list: for image_file in file_list:
self.image_list.append(wx.Bitmap(image_file)) self.image_list.append(wx.Bitmap(image_file))
# bind the panel to the paint event # bind the panel to the paint event
wx.EVT_PAINT(self, self.onPaint) wx.EVT_PAINT(self, self.onPaint)
...@@ -49,7 +49,7 @@ class MyFrame(wx.Frame): ...@@ -49,7 +49,7 @@ class MyFrame(wx.Frame):
if self.mytmpdir: if self.mytmpdir:
shutil.rmtree(self.mytmpdir) shutil.rmtree(self.mytmpdir)
def onPaint(self, event=None): def onPaint(self, event = None):
# this is the wxPython drawing surface/canvas # this is the wxPython drawing surface/canvas
dc = wx.PaintDC(self) dc = wx.PaintDC(self)
while self.loops: while self.loops:
...@@ -59,7 +59,7 @@ class MyFrame(wx.Frame): ...@@ -59,7 +59,7 @@ class MyFrame(wx.Frame):
w, h = bmp.GetSize() w, h = bmp.GetSize()
info = "%s %dx%d" % (self.name_list[ix], w, h) info = "%s %dx%d" % (self.name_list[ix], w, h)
self.SetTitle(info) self.SetTitle(info)
#self.SetSize((w,h)) #self.SetSize((w, h))
# draw the image # draw the image
dc.DrawBitmap(bmp, 0, 0, True) dc.DrawBitmap(bmp, 0, 0, True)
wx.MilliSleep(self.delay) wx.MilliSleep(self.delay)
...@@ -73,4 +73,4 @@ width = 800 ...@@ -73,4 +73,4 @@ width = 800
frameoffset = 35 frameoffset = 35
height = 600 + frameoffset height = 600 + frameoffset
MyFrame(None, (width, height)).Show() MyFrame(None, (width, height)).Show()
app.MainLoop() app.MainLoop()
\ No newline at end of file
...@@ -23,9 +23,9 @@ modify it under the terms of the GNU Lesser General Public License as ...@@ -23,9 +23,9 @@ modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version. License, or (at your option) any later version.
As a special exception, the copyright holders of this library As a special exception, the copyright holders of this library
hereby recind Section 3 of the GNU Lesser General Public License. This hereby recind Section 3 of the GNU Lesser General Public License. This
means that you MAY NOT apply the terms of the ordinary GNU General means that you MAY NOT apply the terms of the ordinary GNU General
Public License instead of this License to any given copy of the Public License instead of this License to any given copy of the
Library. This has been done to prevent users of the Library from being Library. This has been done to prevent users of the Library from being
denied access or the ability to use future improvements. denied access or the ability to use future improvements.
...@@ -66,10 +66,10 @@ class BufferedCanvas(wx.Panel): ...@@ -66,10 +66,10 @@ class BufferedCanvas(wx.Panel):
def __init__(self, def __init__(self,
parent, parent,
ID=-1, ID=-1,
pos=wx.DefaultPosition, pos = wx.DefaultPosition,
size=wx.DefaultSize, size = wx.DefaultSize,
style=wx.NO_FULL_REPAINT_ON_RESIZE|wx.WANTS_CHARS): style = wx.NO_FULL_REPAINT_ON_RESIZE|wx.WANTS_CHARS):
wx.Panel.__init__(self,parent,ID,pos,size,style) wx.Panel.__init__(self, parent, ID, pos, size, style)
# Bind events # Bind events
self.Bind(wx.EVT_PAINT, self.onPaint) self.Bind(wx.EVT_PAINT, self.onPaint)
...@@ -83,7 +83,7 @@ class BufferedCanvas(wx.Panel): ...@@ -83,7 +83,7 @@ class BufferedCanvas(wx.Panel):
## General methods ## General methods
## ##
def draw(self,dc): def draw(self, dc):
""" """
Stub: called when the canvas needs to be re-drawn. Stub: called when the canvas needs to be re-drawn.
""" """
...@@ -94,9 +94,9 @@ class BufferedCanvas(wx.Panel): ...@@ -94,9 +94,9 @@ class BufferedCanvas(wx.Panel):
Causes the canvas to be updated. Causes the canvas to be updated.
""" """
self.Refresh() self.Refresh()
def getWidthHeight(self): def getWidthHeight(self):
width,height = self.GetClientSizeTuple() width, height = self.GetClientSizeTuple()
if width == 0: if width == 0:
width = 1 width = 1
if height == 0: if height == 0:
......
...@@ -2,150 +2,150 @@ ...@@ -2,150 +2,150 @@
#Interactive RepRap e axis calibration program #Interactive RepRap e axis calibration program
#(C) Nathan Zadoks 2011 #(C) Nathan Zadoks 2011
#Licensed under CC-BY-SA or GPLv2 and higher - Pick your poison. #Licensed under CC-BY-SA or GPLv2 and higher - Pick your poison.
s=300 #Extrusion speed (mm/min) s = 300 #Extrusion speed (mm/min)
n=100 #Default length to extrude n = 100 #Default length to extrude
m= 0 #User-entered measured extrusion length m= 0 #User-entered measured extrusion length
k=300 #Default amount of steps per mm k = 300 #Default amount of steps per mm
port='/dev/ttyUSB0' #Default serial port to connect to printer port='/dev/ttyUSB0' #Default serial port to connect to printer
temp=210 #Default extrusion temperature temp = 210 #Default extrusion temperature
tempmax=250 #Maximum extrusion temperature tempmax = 250 #Maximum extrusion temperature
t=int(n*60)/s #Time to wait for extrusion t = int(n*60)/s #Time to wait for extrusion
try: try:
from printdummy import printcore from printdummy import printcore
except ImportError: except ImportError:
from printcore import printcore from printcore import printcore
import time,getopt,sys,os import time, getopt, sys, os
def float_input(prompt=''): def float_input(prompt=''):
import sys import sys
f=None f = None
while f==None: while f == None:
s=raw_input(prompt) s = raw_input(prompt)
try: try:
f=float(s) f = float(s)
except ValueError: except ValueError:
sys.stderr.write("Not a valid floating-point number.\n") sys.stderr.write("Not a valid floating-point number.\n")
sys.stderr.flush() sys.stderr.flush()
return f return f
def wait(t,m=''): def wait(t, m=''):
import time,sys import time, sys
sys.stdout.write(m+'['+(' '*t)+']\r'+m+'[') sys.stdout.write(m+'['+(' '*t)+']\r'+m+'[')
sys.stdout.flush() sys.stdout.flush()
for i in range(t): for i in range(t):
for s in ['|\b','/\b','-\b','\\\b','|']: for s in ['|\b','/\b','-\b','\\\b','|']:
sys.stdout.write(s) sys.stdout.write(s)
sys.stdout.flush() sys.stdout.flush()
time.sleep(1.0/5) time.sleep(1.0/5)
print print
def w(s): def w(s):
sys.stdout.write(s) sys.stdout.write(s)
sys.stdout.flush() sys.stdout.flush()
def heatup(p,temp,s=0): def heatup(p, temp, s = 0):
curtemp=gettemp(p) curtemp = gettemp(p)
p.send_now('M109 S%03d'%temp) p.send_now('M109 S%03d'%temp)
p.temp=0 p.temp = 0
if not s: w("Heating extruder up..") if not s: w("Heating extruder up..")
f=False f = False
while curtemp<=(temp-1): while curtemp<=(temp-1):
p.send_now('M105') p.send_now('M105')
time.sleep(0.5) time.sleep(0.5)
if not f: if not f:
time.sleep(1.5) time.sleep(1.5)
f=True f = True
curtemp=gettemp(p) curtemp = gettemp(p)
if curtemp: w(u"\rHeating extruder up.. %3d \xb0C"%curtemp) if curtemp: w(u"\rHeating extruder up.. %3d \xb0C"%curtemp)
if s: print if s: print
else: print "\nReady." else: print "\nReady."
def gettemp(p): def gettemp(p):
try: p.logl try: p.logl
except: setattr(p,'logl',0) except: setattr(p,'logl',0)
try: p.temp try: p.temp
except: setattr(p,'temp',0) except: setattr(p,'temp',0)
for n in range(p.logl,len(p.log)): for n in range(p.logl, len(p.log)):
line=p.log[n] line = p.log[n]
if 'T:' in line: if 'T:' in line:
try: try:
setattr(p,'temp',int(line.split('T:')[1].split()[0])) setattr(p,'temp',int(line.split('T:')[1].split()[0]))
except: print line except: print line
p.logl=len(p.log) p.logl = len(p.log)
return p.temp return p.temp
if not os.path.exists(port): if not os.path.exists(port):
port=0 port = 0
#Parse options #Parse options
help=u""" help = u"""
%s [ -l DISTANCE ] [ -s STEPS ] [ -t TEMP ] [ -p PORT ] %s [ -l DISTANCE ] [ -s STEPS ] [ -t TEMP ] [ -p PORT ]
-l --length Length of filament to extrude for each calibration step (default: %d mm) -l --length Length of filament to extrude for each calibration step (default: %d mm)
-s --steps Initial amount of steps to use (default: %d steps) -s --steps Initial amount of steps to use (default: %d steps)
-t --temp Extrusion temperature in degrees Celsius (default: %d \xb0C, max %d \xb0C) -t --temp Extrusion temperature in degrees Celsius (default: %d \xb0C, max %d \xb0C)
-p --port Serial port the printer is connected to (default: %s) -p --port Serial port the printer is connected to (default: %s)
-h --help This cruft. -h --help This cruft.
"""[1:-1].encode('utf-8')%(sys.argv[0],n,k,temp,tempmax,port if port else 'auto') """[1:-1].encode('utf-8')%(sys.argv[0], n, k, temp, tempmax, port if port else 'auto')
try: try:
opts,args=getopt.getopt(sys.argv[1:],"hl:s:t:p:",["help","length=","steps=","temp=","port="]) opts, args = getopt.getopt(sys.argv[1:],"hl:s:t:p:",["help", "length=", "steps=", "temp=", "port="])
except getopt.GetoptError,err: except getopt.GetoptError, err:
print str(err) print str(err)
print help print help
sys.exit(2) sys.exit(2)
for o,a in opts: for o, a in opts:
if o in ('-h','--help'): if o in ('-h','--help'):
print help print help
sys.exit() sys.exit()
elif o in ('-l','--length'): elif o in ('-l','--length'):
n=float(a) n = float(a)
elif o in ('-s','--steps'): elif o in ('-s','--steps'):
k=int(a) k = int(a)
elif o in ('-t','--temp'): elif o in ('-t','--temp'):
temp=int(a) temp = int(a)
if temp>=tempmax: if temp>=tempmax:
print (u'%d \xb0C? Are you insane?'.encode('utf-8')%temp)+(" That's over nine thousand!" if temp>9000 else '') print (u'%d \xb0C? Are you insane?'.encode('utf-8')%temp)+(" That's over nine thousand!" if temp>9000 else '')
sys.exit(255) sys.exit(255)
elif o in ('-p','--port'): elif o in ('-p','--port'):
port=a port = a
#Show initial parameters #Show initial parameters
print "Initial parameters" print "Initial parameters"
print "Steps per mm: %3d steps"%k print "Steps per mm: %3d steps"%k
print "Length extruded: %3d mm"%n print "Length extruded: %3d mm"%n
print print
print "Serial port: %s"%(port if port else 'auto') print "Serial port: %s"%(port if port else 'auto')
p=None p = None
try: try:
#Connect to printer #Connect to printer
w("Connecting to printer..") w("Connecting to printer..")
try: try:
p=printcore(port,115200) p = printcore(port, 115200)
except: except:
print 'Error.' print 'Error.'
raise raise
while not p.online: while not p.online:
time.sleep(1) time.sleep(1)
w('.') w('.')
print " connected." print " connected."
heatup(p,temp) heatup(p, temp)
#Calibration loop #Calibration loop
while n!=m: while n!=m:
heatup(p,temp,True) heatup(p, temp, True)
p.send_now("G92 E0") #Reset e axis p.send_now("G92 E0") #Reset e axis
p.send_now("G1 E%d F%d"%(n,s)) #Extrude length of filament p.send_now("G1 E%d F%d"%(n, s)) #Extrude length of filament
wait(t,'Extruding.. ') wait(t,'Extruding.. ')
m=float_input("How many millimeters of filament were extruded? ") m = float_input("How many millimeters of filament were extruded? ")
if m==0: continue if m == 0: continue
if n!=m: if n!=m:
k=(n/m)*k k = (n/m)*k
p.send_now("M92 E%d"%int(round(k))) #Set new step count p.send_now("M92 E%d"%int(round(k))) #Set new step count
print "Steps per mm: %3d steps"%k #Tell user print "Steps per mm: %3d steps"%k #Tell user
print 'Calibration completed.' #Yay! print 'Calibration completed.' #Yay!
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass
finally: finally:
if p: p.disconnect() if p: p.disconnect()
...@@ -19,8 +19,8 @@ import threading ...@@ -19,8 +19,8 @@ import threading
class GLPanel(wx.Panel): class GLPanel(wx.Panel):
'''A simple class for using OpenGL with wxPython.''' '''A simple class for using OpenGL with wxPython.'''
def __init__(self, parent, id, pos=wx.DefaultPosition, def __init__(self, parent, id, pos = wx.DefaultPosition,
size=wx.DefaultSize, style=0): size = wx.DefaultSize, style = 0):
# Forcing a no full repaint to stop flickering # Forcing a no full repaint to stop flickering
style = style | wx.NO_FULL_REPAINT_ON_RESIZE style = style | wx.NO_FULL_REPAINT_ON_RESIZE
#call super function #call super function
...@@ -33,7 +33,7 @@ class GLPanel(wx.Panel): ...@@ -33,7 +33,7 @@ class GLPanel(wx.Panel):
glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit
# Create the canvas # Create the canvas
self.sizer = wx.BoxSizer(wx.HORIZONTAL) self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.canvas = glcanvas.GLCanvas(self, attribList=attribList) self.canvas = glcanvas.GLCanvas(self, attribList = attribList)
self.sizer.Add(self.canvas, 1, wx.EXPAND) self.sizer.Add(self.canvas, 1, wx.EXPAND)
self.SetSizer(self.sizer) self.SetSizer(self.sizer)
#self.sizer.Fit(self) #self.sizer.Fit(self)
...@@ -200,7 +200,7 @@ def _dist(dist): ...@@ -200,7 +200,7 @@ def _dist(dist):
class gcpoint(object): class gcpoint(object):
"""gcode point """gcode point
stub for first line""" stub for first line"""
def __init__(self, x=0,y=0,z=0,e=0): def __init__(self, x = 0, y = 0, z = 0, e = 0):
self.x = x self.x = x
self.y = y self.y = y
self.z = z self.z = z
...@@ -210,10 +210,10 @@ class gcpoint(object): ...@@ -210,10 +210,10 @@ class gcpoint(object):
class gcline(object): class gcline(object):
"""gcode move line """gcode move line
Once initialised,it knows its position, length and extrusion ratio Once initialised, it knows its position, length and extrusion ratio
Returns lines into gcview batch() Returns lines into gcview batch()
""" """
def __init__(self, x=None, y=None, z=None, e=None, f=None, prev_gcline=None, orgline = False): def __init__(self, x = None, y = None, z = None, e = None, f = None, prev_gcline = None, orgline = False):
if prev_gcline is None: if prev_gcline is None:
self.prev_gcline = gcpoint() self.prev_gcline = gcpoint()
else: else:
...@@ -255,7 +255,7 @@ class gcline(object): ...@@ -255,7 +255,7 @@ class gcline(object):
self.orgline, self.orgline,
) )
def calc_delta(self, prev_gcline=None): def calc_delta(self, prev_gcline = None):
if prev_gcline is None: if prev_gcline is None:
prev_gcline = self.prev_gcline prev_gcline = self.prev_gcline
if self.prev_gcline is not None: if self.prev_gcline is not None:
...@@ -290,7 +290,7 @@ class gcline(object): ...@@ -290,7 +290,7 @@ class gcline(object):
] ]
def glcolor(self, upper_limit = None, lower_limit = 0, max_feedrate = 0): def glcolor(self, upper_limit = None, lower_limit = 0, max_feedrate = 0):
if self.extrusion_ratio == 0: if self.extrusion_ratio == 0:
return [255,255,255,0,0,0] return [255, 255, 255, 0, 0, 0]
else: else:
blue_color = 0 blue_color = 0
green_color = 0 green_color = 0
...@@ -312,7 +312,7 @@ class gcline(object): ...@@ -312,7 +312,7 @@ class gcline(object):
blue_color = 255 blue_color = 255
if blue_color < 0: if blue_color < 0:
blue_color = 0 blue_color = 0
return[255,green_color,blue_color,128,green_color,blue_color/4] return[255, green_color, blue_color, 128, green_color, blue_color/4]
def float_from_line(axe, line): def float_from_line(axe, line):
...@@ -340,7 +340,7 @@ class gcview(object): ...@@ -340,7 +340,7 @@ class gcview(object):
"""gcode visualiser """gcode visualiser
Holds opengl objects for all layers Holds opengl objects for all layers
""" """
def __init__(self, lines, batch, w=0.5, h=0.5): def __init__(self, lines, batch, w = 0.5, h = 0.5):
if len(lines) == 0: if len(lines) == 0:
return return
print "Loading %s lines" % (len(lines)) print "Loading %s lines" % (len(lines))
...@@ -430,7 +430,7 @@ class gcview(object): ...@@ -430,7 +430,7 @@ class gcview(object):
else: else:
self.lastf = cur[4] self.lastf = cur[4]
r = gcline(x=cur[0], y=cur[1], z=cur[2],e=cur[3], f=cur[4], prev_gcline=self.prev, orgline=orgline) r = gcline(x = cur[0], y = cur[1], z = cur[2], e = cur[3], f = cur[4], prev_gcline = self.prev, orgline = orgline)
self.prev = r self.prev = r
return r return r
return None return None
...@@ -524,7 +524,7 @@ def mulquat(q1, rq): ...@@ -524,7 +524,7 @@ def mulquat(q1, rq):
class TestGlPanel(GLPanel): class TestGlPanel(GLPanel):
def __init__(self, parent, size, id=wx.ID_ANY): def __init__(self, parent, size, id = wx.ID_ANY):
super(TestGlPanel, self).__init__(parent, id, wx.DefaultPosition, size, 0) super(TestGlPanel, self).__init__(parent, id, wx.DefaultPosition, size, 0)
self.batches = [] self.batches = []
self.rot = 0 self.rot = 0
...@@ -553,7 +553,7 @@ class TestGlPanel(GLPanel): ...@@ -553,7 +553,7 @@ class TestGlPanel(GLPanel):
def forceresize(self): def forceresize(self):
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1)) self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1))
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] - 1)) self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] - 1))
threading.Thread(target=self.update).start() threading.Thread(target = self.update).start()
self.initialized = 0 self.initialized = 0
def move_shape(self, delta): def move_shape(self, delta):
...@@ -605,7 +605,7 @@ class TestGlPanel(GLPanel): ...@@ -605,7 +605,7 @@ class TestGlPanel(GLPanel):
p1y = -(float(p1[1]) - sz[1] / 2) / (sz[1] / 2) p1y = -(float(p1[1]) - sz[1] / 2) / (sz[1] / 2)
p2x = (float(p2[0]) - sz[0] / 2) / (sz[0] / 2) p2x = (float(p2[0]) - sz[0] / 2) / (sz[0] / 2)
p2y = -(float(p2[1]) - sz[1] / 2) / (sz[1] / 2) p2y = -(float(p2[1]) - sz[1] / 2) / (sz[1] / 2)
#print p1x,p1y,p2x,p2y #print p1x, p1y, p2x, p2y
quat = trackball(p1x, p1y, p2x, p2y, -self.transv[2] / 250.0) quat = trackball(p1x, p1y, p2x, p2y, -self.transv[2] / 250.0)
if self.rot: if self.rot:
self.basequat = mulquat(self.basequat, quat) self.basequat = mulquat(self.basequat, quat)
...@@ -768,7 +768,7 @@ class TestGlPanel(GLPanel): ...@@ -768,7 +768,7 @@ class TestGlPanel(GLPanel):
def drawmodel(self, m, n): def drawmodel(self, m, n):
batch = pyglet.graphics.Batch() batch = pyglet.graphics.Batch()
stl = stlview(m.facets, batch=batch) stl = stlview(m.facets, batch = batch)
m.batch = batch m.batch = batch
m.animoffset = 300 m.animoffset = 300
#print m #print m
...@@ -907,8 +907,8 @@ class TestGlPanel(GLPanel): ...@@ -907,8 +907,8 @@ class TestGlPanel(GLPanel):
class GCFrame(wx.Frame): class GCFrame(wx.Frame):
'''A simple class for using OpenGL with wxPython.''' '''A simple class for using OpenGL with wxPython.'''
def __init__(self, parent, ID, title, pos=wx.DefaultPosition, def __init__(self, parent, ID, title, pos = wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE): size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
super(GCFrame, self).__init__(parent, ID, title, pos, (size[0] + 150, size[1]), style) super(GCFrame, self).__init__(parent, ID, title, pos, (size[0] + 150, size[1]), style)
class d: class d:
...@@ -921,22 +921,22 @@ class GCFrame(wx.Frame): ...@@ -921,22 +921,22 @@ class GCFrame(wx.Frame):
m.curlayer = -1 m.curlayer = -1
m.scale = [1.0, 1.0, 1.0] m.scale = [1.0, 1.0, 1.0]
m.batch = pyglet.graphics.Batch() m.batch = pyglet.graphics.Batch()
m.gc = gcview([], batch=m.batch) m.gc = gcview([], batch = m.batch)
self.models = {"GCODE": m} self.models = {"GCODE": m}
self.l = d() self.l = d()
self.modelindex = 0 self.modelindex = 0
self.GLPanel1 = TestGlPanel(self, size) self.GLPanel1 = TestGlPanel(self, size)
def addfile(self, gcode=[]): def addfile(self, gcode = []):
self.models["GCODE"].gc.delete() self.models["GCODE"].gc.delete()
self.models["GCODE"].gc = gcview(gcode, batch=self.models["GCODE"].batch) self.models["GCODE"].gc = gcview(gcode, batch = self.models["GCODE"].batch)
self.setlayerindex(None) self.setlayerindex(None)
def clear(self): def clear(self):
self.models["GCODE"].gc.delete() self.models["GCODE"].gc.delete()
self.models["GCODE"].gc = gcview([], batch=self.models["GCODE"].batch) self.models["GCODE"].gc = gcview([], batch = self.models["GCODE"].batch)
def Show(self, arg=True): def Show(self, arg = True):
wx.Frame.Show(self, arg) wx.Frame.Show(self, arg)
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1)) self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1))
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] - 1)) self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] - 1))
...@@ -975,8 +975,8 @@ class GCFrame(wx.Frame): ...@@ -975,8 +975,8 @@ class GCFrame(wx.Frame):
def main(): def main():
app = wx.App(redirect=False) app = wx.App(redirect = False)
frame = GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size=(400, 400)) frame = GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size = (400, 400))
import sys import sys
for filename in sys.argv: for filename in sys.argv:
if ".gcode" in filename: if ".gcode" in filename:
...@@ -985,8 +985,8 @@ def main(): ...@@ -985,8 +985,8 @@ def main():
#TODO: add stl here #TODO: add stl here
pass pass
#frame = wx.Frame(None, -1, "GL Window", size=(400, 400)) #frame = wx.Frame(None, -1, "GL Window", size = (400, 400))
#panel = TestGlPanel(frame, size=(300,300)) #panel = TestGlPanel(frame, size = (300, 300))
frame.Show(True) frame.Show(True)
app.MainLoop() app.MainLoop()
app.Destroy() app.Destroy()
......
...@@ -22,8 +22,8 @@ from bufferedcanvas import * ...@@ -22,8 +22,8 @@ from bufferedcanvas import *
class Graph(BufferedCanvas): class Graph(BufferedCanvas):
'''A class to show a Graph with Pronterface.''' '''A class to show a Graph with Pronterface.'''
def __init__(self, parent, id, pos=wx.DefaultPosition, def __init__(self, parent, id, pos = wx.DefaultPosition,
size=wx.DefaultSize, style=0): size = wx.DefaultSize, style = 0):
# Forcing a no full repaint to stop flickering # Forcing a no full repaint to stop flickering
style = style | wx.NO_FULL_REPAINT_ON_RESIZE style = style | wx.NO_FULL_REPAINT_ON_RESIZE
#call super function #call super function
...@@ -53,7 +53,7 @@ class Graph(BufferedCanvas): ...@@ -53,7 +53,7 @@ class Graph(BufferedCanvas):
#self.sizer = wx.BoxSizer(wx.HORIZONTAL) #self.sizer = wx.BoxSizer(wx.HORIZONTAL)
#self.sizer.Add(wx.Button(self, -1, "Button1", (0,0))) #self.sizer.Add(wx.Button(self, -1, "Button1", (0, 0)))
#self.SetSizer(self.sizer) #self.SetSizer(self.sizer)
...@@ -78,23 +78,23 @@ class Graph(BufferedCanvas): ...@@ -78,23 +78,23 @@ class Graph(BufferedCanvas):
def drawgrid(self, dc, gc): def drawgrid(self, dc, gc):
#cold,medium,hot = wx.Colour(0,167,223),wx.Colour(239,233,119),wx.Colour(210,50.100) #cold, medium, hot = wx.Colour(0, 167, 223), wx.Colour(239, 233, 119), wx.Colour(210, 50.100)
#col1 = wx.Colour(255,0,0, 255) #col1 = wx.Colour(255, 0, 0, 255)
#col2 = wx.Colour(255,255,255, 128) #col2 = wx.Colour(255, 255, 255, 128)
#b = gc.CreateLinearGradientBrush(0, 0, w, h, col1, col2) #b = gc.CreateLinearGradientBrush(0, 0, w, h, col1, col2)
gc.SetPen(wx.Pen(wx.Colour(255,0,0,0), 4)) gc.SetPen(wx.Pen(wx.Colour(255, 0, 0, 0), 4))
#gc.SetBrush(gc.CreateBrush(wx.Brush(wx.Colour(245,245,255,252)))) #gc.SetBrush(gc.CreateBrush(wx.Brush(wx.Colour(245, 245, 255, 252))))
#gc.SetBrush(b) #gc.SetBrush(b)
gc.DrawRectangle(0, 0, self.width, self.height) gc.DrawRectangle(0, 0, self.width, self.height)
#gc.SetBrush(wx.Brush(wx.Colour(245,245,255,52))) #gc.SetBrush(wx.Brush(wx.Colour(245, 245, 255, 52)))
#gc.SetBrush(gc.CreateBrush(wx.Brush(wx.Colour(0,0,0,255)))) #gc.SetBrush(gc.CreateBrush(wx.Brush(wx.Colour(0, 0, 0, 255))))
#gc.SetPen(wx.Pen(wx.Colour(255,0,0,0), 4)) #gc.SetPen(wx.Pen(wx.Colour(255, 0, 0, 0), 4))
#gc.DrawLines(wx.Point(0,0), wx.Point(50,10)) #gc.DrawLines(wx.Point(0, 0), wx.Point(50, 10))
#path = gc.CreatePath() #path = gc.CreatePath()
#path.MoveToPoint(0.0, 0.0) #path.MoveToPoint(0.0, 0.0)
...@@ -107,34 +107,34 @@ class Graph(BufferedCanvas): ...@@ -107,34 +107,34 @@ class Graph(BufferedCanvas):
font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD) font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD)
gc.SetFont(font, wx.Colour(23,44,44)) gc.SetFont(font, wx.Colour(23, 44, 44))
dc.SetPen(wx.Pen(wx.Colour(225,225,225), 1)) dc.SetPen(wx.Pen(wx.Colour(225, 225, 225), 1))
for x in range(self.xbars): for x in range(self.xbars):
dc.DrawLine(x*(float(self.width)/self.xbars), 0, x*(float(self.width)/self.xbars), self.height) dc.DrawLine(x*(float(self.width)/self.xbars), 0, x*(float(self.width)/self.xbars), self.height)
dc.SetPen(wx.Pen(wx.Colour(225,225,225), 1)) dc.SetPen(wx.Pen(wx.Colour(225, 225, 225), 1))
for y in range(self.ybars): for y in range(self.ybars):
y_pos = y*(float(self.height)/self.ybars) y_pos = y*(float(self.height)/self.ybars)
dc.DrawLine(0,y_pos, self.width,y_pos) dc.DrawLine(0, y_pos, self.width, y_pos)
gc.DrawText(unicode(int(self.maxyvalue - (y * (self.maxyvalue/self.ybars)))), 1, y_pos - (font.GetPointSize() / 2)) gc.DrawText(unicode(int(self.maxyvalue - (y * (self.maxyvalue/self.ybars)))), 1, y_pos - (font.GetPointSize() / 2))
if self.timer.IsRunning() == False: if self.timer.IsRunning() == False:
font = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD) font = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD)
gc.SetFont(font, wx.Colour(3,4,4)) gc.SetFont(font, wx.Colour(3, 4, 4))
gc.DrawText("Graph offline", self.width/2 - (font.GetPointSize() * 3), self.height/2 - (font.GetPointSize() * 1)) gc.DrawText("Graph offline", self.width/2 - (font.GetPointSize() * 3), self.height/2 - (font.GetPointSize() * 1))
#dc.DrawCircle(50,50, 1) #dc.DrawCircle(50, 50, 1)
#gc.SetPen(wx.Pen(wx.Colour(255,0,0,0), 1)) #gc.SetPen(wx.Pen(wx.Colour(255, 0, 0, 0), 1))
#gc.DrawLines([[20,30], [10,53]]) #gc.DrawLines([[20, 30], [10, 53]])
#dc.SetPen(wx.Pen(wx.Colour(255,0,0,0), 1)) #dc.SetPen(wx.Pen(wx.Colour(255, 0, 0, 0), 1))
def drawtemperature(self, dc, gc, temperature_list, text, text_xoffset, r, g, b, a): def drawtemperature(self, dc, gc, temperature_list, text, text_xoffset, r, g, b, a):
if self.timer.IsRunning() == False: if self.timer.IsRunning() == False:
dc.SetPen(wx.Pen(wx.Colour(128,128,128,128), 1)) dc.SetPen(wx.Pen(wx.Colour(128, 128, 128, 128), 1))
else: else:
dc.SetPen(wx.Pen(wx.Colour(r,g,b,a), 1)) dc.SetPen(wx.Pen(wx.Colour(r, g, b, a), 1))
x_add = float(self.width)/self.xsteps x_add = float(self.width)/self.xsteps
x_pos = float(0.0) x_pos = float(0.0)
...@@ -143,7 +143,7 @@ class Graph(BufferedCanvas): ...@@ -143,7 +143,7 @@ class Graph(BufferedCanvas):
for temperature in (temperature_list): for temperature in (temperature_list):
y_pos = int((float(self.height-self.y_offset)/self.maxyvalue)*temperature) + self.y_offset y_pos = int((float(self.height-self.y_offset)/self.maxyvalue)*temperature) + self.y_offset
if (x_pos > 0.0): # One need 2 points to draw a line. if (x_pos > 0.0): # One need 2 points to draw a line.
dc.DrawLine(lastxvalue,self.height-self._lastyvalue, x_pos, self.height-y_pos) dc.DrawLine(lastxvalue, self.height-self._lastyvalue, x_pos, self.height-y_pos)
lastxvalue = x_pos lastxvalue = x_pos
x_pos = float(x_pos) + x_add x_pos = float(x_pos) + x_add
...@@ -153,9 +153,9 @@ class Graph(BufferedCanvas): ...@@ -153,9 +153,9 @@ class Graph(BufferedCanvas):
font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD) font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.BOLD)
#font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL) #font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
if self.timer.IsRunning() == False: if self.timer.IsRunning() == False:
gc.SetFont(font, wx.Colour(128,128,128)) gc.SetFont(font, wx.Colour(128, 128, 128))
else: else:
gc.SetFont(font, wx.Colour(r,g,b)) gc.SetFont(font, wx.Colour(r, g, b))
#gc.DrawText(text, self.width - (font.GetPointSize() * ((len(text) * text_xoffset + 1))), self.height - self._lastyvalue - (font.GetPointSize() / 2)) #gc.DrawText(text, self.width - (font.GetPointSize() * ((len(text) * text_xoffset + 1))), self.height - self._lastyvalue - (font.GetPointSize() / 2))
gc.DrawText(text, x_pos - x_add - (font.GetPointSize() * ((len(text) * text_xoffset + 1))), self.height - self._lastyvalue - (font.GetPointSize() / 2)) gc.DrawText(text, x_pos - x_add - (font.GetPointSize() * ((len(text) * text_xoffset + 1))), self.height - self._lastyvalue - (font.GetPointSize() / 2))
...@@ -163,24 +163,24 @@ class Graph(BufferedCanvas): ...@@ -163,24 +163,24 @@ class Graph(BufferedCanvas):
def drawbedtemp(self, dc, gc): def drawbedtemp(self, dc, gc):
self.drawtemperature(dc, gc, self.bedtemps, "Bed",2, 255,0,0, 128) self.drawtemperature(dc, gc, self.bedtemps, "Bed", 2, 255, 0, 0, 128)
def drawbedtargettemp(self, dc, gc): def drawbedtargettemp(self, dc, gc):
self.drawtemperature(dc, gc, self.bedtargettemps, "Bed Target",2, 255,120,0, 128) self.drawtemperature(dc, gc, self.bedtargettemps, "Bed Target", 2, 255, 120, 0, 128)
def drawextruder0temp(self, dc, gc): def drawextruder0temp(self, dc, gc):
self.drawtemperature(dc, gc, self.extruder0temps, "Ex0",1, 0,155,255, 128) self.drawtemperature(dc, gc, self.extruder0temps, "Ex0", 1, 0, 155, 255, 128)
def drawextruder0targettemp(self, dc, gc): def drawextruder0targettemp(self, dc, gc):
self.drawtemperature(dc, gc, self.extruder0targettemps, "Ex0 Target",2, 0,5,255, 128) self.drawtemperature(dc, gc, self.extruder0targettemps, "Ex0 Target", 2, 0, 5, 255, 128)
def drawextruder1temp(self, dc, gc): def drawextruder1temp(self, dc, gc):
self.drawtemperature(dc, gc, self.extruder1temps, "Ex1",3, 55,55,0, 128) self.drawtemperature(dc, gc, self.extruder1temps, "Ex1", 3, 55, 55, 0, 128)
def drawextruder1targettemp(self, dc, gc): def drawextruder1targettemp(self, dc, gc):
self.drawtemperature(dc, gc, self.extruder1targettemps, "Ex1 Target",2, 55,55,0, 128) self.drawtemperature(dc, gc, self.extruder1targettemps, "Ex1 Target", 2, 55, 55, 0, 128)
def SetBedTemperature(self, value): def SetBedTemperature(self, value):
...@@ -263,5 +263,3 @@ class Graph(BufferedCanvas): ...@@ -263,5 +263,3 @@ class Graph(BufferedCanvas):
self.drawextruder0temp(dc, gc) self.drawextruder0temp(dc, gc)
self.drawextruder1targettemp(dc, gc) self.drawextruder1targettemp(dc, gc)
self.drawextruder1temp(dc, gc) self.drawextruder1temp(dc, gc)
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import wx,time import wx, time
from printrun_utils import imagefile from printrun_utils import imagefile
ID_ABOUT = 101 ID_ABOUT = 101
ID_EXIT = 110 ID_EXIT = 110
class window(wx.Frame): class window(wx.Frame):
def __init__(self,f,size=(600,600),build_dimensions=[200,200,100,0,0,0],grid=(10,50),extrusion_width=0.5): def __init__(self, f, size = (600, 600), build_dimensions = [200, 200, 100, 0, 0, 0], grid = (10, 50), extrusion_width = 0.5):
wx.Frame.__init__(self,None,title="Gcode view, shift to move view, mousewheel to set layer",size=(size[0],size[1])) wx.Frame.__init__(self, None, title = "Gcode view, shift to move view, mousewheel to set layer", size = (size[0], size[1]))
self.p=gviz(self,size=size,build_dimensions=build_dimensions,grid=grid,extrusion_width=extrusion_width) self.p = gviz(self, size = size, build_dimensions = build_dimensions, grid = grid, extrusion_width = extrusion_width)
vbox = wx.BoxSizer(wx.VERTICAL) vbox = wx.BoxSizer(wx.VERTICAL)
toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER) toolbar = wx.ToolBar(self, -1, style = wx.TB_HORIZONTAL | wx.NO_BORDER)
toolbar.AddSimpleTool(1, wx.Image(imagefile('zoom_in.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom In [+]', '') toolbar.AddSimpleTool(1, wx.Image(imagefile('zoom_in.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom In [+]', '')
toolbar.AddSimpleTool(2, wx.Image(imagefile('zoom_out.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom Out [-]', '') toolbar.AddSimpleTool(2, wx.Image(imagefile('zoom_out.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom Out [-]', '')
toolbar.AddSeparator() toolbar.AddSeparator()
toolbar.AddSimpleTool(3, wx.Image(imagefile('arrow_up.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Move Up a Layer [U]', '') toolbar.AddSimpleTool(3, wx.Image(imagefile('arrow_up.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Move Up a Layer [U]', '')
toolbar.AddSimpleTool(4, wx.Image(imagefile('arrow_down.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Move Down a Layer [D]', '') toolbar.AddSimpleTool(4, wx.Image(imagefile('arrow_down.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Move Down a Layer [D]', '')
toolbar.AddSimpleTool(5, wx.EmptyBitmap(16,16), 'Reset view', '') toolbar.AddSimpleTool(5, wx.EmptyBitmap(16, 16), 'Reset view', '')
toolbar.AddSeparator() toolbar.AddSeparator()
#toolbar.AddSimpleTool(5, wx.Image('./images/inject.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Insert Code at start of this layer', '') #toolbar.AddSimpleTool(5, wx.Image('./images/inject.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Insert Code at start of this layer', '')
toolbar.Realize() toolbar.Realize()
vbox.Add(toolbar, 0, border=5) vbox.Add(toolbar, 0, border = 5)
self.SetSizer(vbox) self.SetSizer(vbox)
self.Bind(wx.EVT_TOOL, lambda x:self.p.zoom(200,200,1.2), id=1) self.Bind(wx.EVT_TOOL, lambda x:self.p.zoom(200, 200, 1.2), id = 1)
self.Bind(wx.EVT_TOOL, lambda x:self.p.zoom(200,200,1/1.2), id=2) self.Bind(wx.EVT_TOOL, lambda x:self.p.zoom(200, 200, 1/1.2), id = 2)
self.Bind(wx.EVT_TOOL, lambda x:self.p.layerup(), id=3) self.Bind(wx.EVT_TOOL, lambda x:self.p.layerup(), id = 3)
self.Bind(wx.EVT_TOOL, lambda x:self.p.layerdown(), id=4) self.Bind(wx.EVT_TOOL, lambda x:self.p.layerdown(), id = 4)
self.Bind(wx.EVT_TOOL, self.resetview, id=5) self.Bind(wx.EVT_TOOL, self.resetview, id = 5)
#self.Bind(wx.EVT_TOOL, lambda x:self.p.inject(), id=5) #self.Bind(wx.EVT_TOOL, lambda x:self.p.inject(), id = 5)
self.CreateStatusBar(1); self.CreateStatusBar(1);
self.SetStatusText("Layer number and Z position show here when you scroll"); self.SetStatusText("Layer number and Z position show here when you scroll");
#self.bu=wx.Button(self.p,-1,"U",pos=(0,100),size=(40,140)) #self.bu = wx.Button(self.p,-1, "U", pos = (0, 100), size = (40, 140))
#self.bd=wx.Button(self.p,-1,"D",pos=(0,140),size=(40,140)) #self.bd = wx.Button(self.p,-1, "D", pos = (0, 140), size = (40, 140))
#self.bi=wx.Button(self.p,-1,"+",pos=(40,100),size=(40,140)) #self.bi = wx.Button(self.p,-1, "+", pos = (40, 100), size = (40, 140))
#self.bo=wx.Button(self.p,-1,"-",pos=(40,140),size=(40,140)) #self.bo = wx.Button(self.p,-1, "-", pos = (40, 140), size = (40, 140))
#self.bs=wx.Button(self.p, -1, "Inject", pos=(85, 103), size=(50, 20)) #self.bs = wx.Button(self.p, -1, "Inject", pos = (85, 103), size = (50, 20))
#self.bu.SetToolTip(wx.ToolTip("Move up one layer")) #self.bu.SetToolTip(wx.ToolTip("Move up one layer"))
#self.bd.SetToolTip(wx.ToolTip("Move down one layer")) #self.bd.SetToolTip(wx.ToolTip("Move down one layer"))
#self.bi.SetToolTip(wx.ToolTip("Zoom view in")) #self.bi.SetToolTip(wx.ToolTip("Zoom view in"))
#self.bo.SetToolTip(wx.ToolTip("Zoom view out")) #self.bo.SetToolTip(wx.ToolTip("Zoom view out"))
#self.bs.SetToolTip(wx.ToolTip("Insert Code at start of this layer")) #self.bs.SetToolTip(wx.ToolTip("Insert Code at start of this layer"))
#self.bu.Bind(wx.EVT_BUTTON,lambda x:self.p.layerup()) #self.bu.Bind(wx.EVT_BUTTON, lambda x:self.p.layerup())
#self.bd.Bind(wx.EVT_BUTTON,lambda x:self.p.layerdown()) #self.bd.Bind(wx.EVT_BUTTON, lambda x:self.p.layerdown())
#self.bi.Bind(wx.EVT_BUTTON,lambda x:self.p.zoom(200,200,1.2)) #self.bi.Bind(wx.EVT_BUTTON, lambda x:self.p.zoom(200, 200, 1.2))
#self.bo.Bind(wx.EVT_BUTTON,lambda x:self.p.zoom(200,200,1/1.2)) #self.bo.Bind(wx.EVT_BUTTON, lambda x:self.p.zoom(200, 200, 1/1.2))
#self.bs.Bind(wx.EVT_BUTTON,lambda x:self.p.inject()) #self.bs.Bind(wx.EVT_BUTTON, lambda x:self.p.inject())
s=time.time() s = time.time()
#print time.time()-s #print time.time()-s
self.initpos=[0,0] self.initpos = [0, 0]
self.p.Bind(wx.EVT_KEY_DOWN,self.key) self.p.Bind(wx.EVT_KEY_DOWN, self.key)
#self.bu.Bind(wx.EVT_KEY_DOWN,self.key) #self.bu.Bind(wx.EVT_KEY_DOWN, self.key)
#self.bd.Bind(wx.EVT_KEY_DOWN,self.key) #self.bd.Bind(wx.EVT_KEY_DOWN, self.key)
#self.bi.Bind(wx.EVT_KEY_DOWN,self.key) #self.bi.Bind(wx.EVT_KEY_DOWN, self.key)
#self.bo.Bind(wx.EVT_KEY_DOWN,self.key) #self.bo.Bind(wx.EVT_KEY_DOWN, self.key)
self.Bind(wx.EVT_KEY_DOWN,self.key) self.Bind(wx.EVT_KEY_DOWN, self.key)
self.p.Bind(wx.EVT_MOUSEWHEEL,self.zoom) self.p.Bind(wx.EVT_MOUSEWHEEL, self.zoom)
self.Bind(wx.EVT_MOUSEWHEEL,self.zoom) self.Bind(wx.EVT_MOUSEWHEEL, self.zoom)
self.p.Bind(wx.EVT_MOUSE_EVENTS,self.mouse) self.p.Bind(wx.EVT_MOUSE_EVENTS, self.mouse)
self.Bind(wx.EVT_MOUSE_EVENTS,self.mouse) self.Bind(wx.EVT_MOUSE_EVENTS, self.mouse)
def resetview(self,event): def resetview(self, event):
self.p.translate=[0.0,0.0] self.p.translate = [0.0, 0.0]
self.p.scale=self.p.basescale self.p.scale = self.p.basescale
self.p.zoom(0,0,1.0) self.p.zoom(0, 0, 1.0)
def mouse(self,event): def mouse(self, event):
if event.ButtonUp(wx.MOUSE_BTN_LEFT): if event.ButtonUp(wx.MOUSE_BTN_LEFT):
if(self.initpos is not None): if(self.initpos is not None):
self.initpos=None self.initpos = None
elif event.Dragging(): elif event.Dragging():
e=event.GetPositionTuple() e = event.GetPositionTuple()
if self.initpos is None or not hasattr(self,"basetrans"): if self.initpos is None or not hasattr(self, "basetrans"):
self.initpos=e self.initpos = e
self.basetrans=self.p.translate self.basetrans = self.p.translate
#print self.p.translate,e,self.initpos #print self.p.translate, e, self.initpos
self.p.translate = [ self.basetrans[0]+(e[0]-self.initpos[0]), self.p.translate = [ self.basetrans[0]+(e[0]-self.initpos[0]),
self.basetrans[1]+(e[1]-self.initpos[1]) ] self.basetrans[1]+(e[1]-self.initpos[1]) ]
self.p.repaint() self.p.repaint()
self.p.Refresh() self.p.Refresh()
else: else:
event.Skip() event.Skip()
def key(self, event): def key(self, event):
# Keycode definitions # Keycode definitions
kup=[85, 315] # Up keys kup = [85, 315] # Up keys
kdo=[68, 317] # Down Keys kdo = [68, 317] # Down Keys
kzi=[388, 316, 61] # Zoom In Keys kzi = [388, 316, 61] # Zoom In Keys
kzo=[390, 314, 45] # Zoom Out Keys kzo = [390, 314, 45] # Zoom Out Keys
x=event.GetKeyCode() x = event.GetKeyCode()
#print "Key event - "+str(x) #print "Key event - "+str(x)
#if event.ShiftDown(): #if event.ShiftDown():
cx,cy=self.p.translate cx, cy = self.p.translate
# if x==wx.WXK_UP: # if x == wx.WXK_UP:
# self.p.zoom(cx,cy,1.2) # self.p.zoom(cx, cy, 1.2)
# if x==wx.WXK_DOWN: # if x == wx.WXK_DOWN:
# self.p.zoom(cx,cy,1/1.2) # self.p.zoom(cx, cy, 1/1.2)
#else: #else:
# if x==wx.WXK_UP: # if x == wx.WXK_UP:
# self.p.layerup() # self.p.layerup()
# if x==wx.WXK_DOWN: # if x == wx.WXK_DOWN:
# self.p.layerdown() # self.p.layerdown()
if x in kup: if x in kup:
self.p.layerup() self.p.layerup()
if x in kdo: if x in kdo:
self.p.layerdown() self.p.layerdown()
if x in kzi: if x in kzi:
self.p.zoom(cx,cy,1.2) self.p.zoom(cx, cy, 1.2)
if x in kzo: if x in kzo:
self.p.zoom(cx, cy, 1/1.2) self.p.zoom(cx, cy, 1/1.2)
#print p.lines.keys() #print p.lines.keys()
def zoom(self, event): def zoom(self, event):
z=event.GetWheelRotation() z = event.GetWheelRotation()
if event.ShiftDown(): if event.ShiftDown():
if z > 0: self.p.layerdown() if z > 0: self.p.layerdown()
elif z < 0: self.p.layerup() elif z < 0: self.p.layerup()
else: else:
if z > 0: self.p.zoom(event.GetX(),event.GetY(),1.2) if z > 0: self.p.zoom(event.GetX(), event.GetY(), 1.2)
elif z < 0: self.p.zoom(event.GetX(),event.GetY(),1/1.2) elif z < 0: self.p.zoom(event.GetX(), event.GetY(), 1/1.2)
class gviz(wx.Panel): class gviz(wx.Panel):
def __init__(self,parent,size=(200,200),build_dimensions=[200,200,100,0,0,0],grid=(10,50),extrusion_width=0.5): def __init__(self, parent, size = (200, 200), build_dimensions = [200, 200, 100, 0, 0, 0], grid = (10, 50), extrusion_width = 0.5):
wx.Panel.__init__(self,parent,-1,size=(size[0],size[1])) wx.Panel.__init__(self, parent,-1, size = (size[0], size[1]))
self.parent=parent self.parent = parent
self.size=size self.size = size
self.build_dimensions=build_dimensions self.build_dimensions = build_dimensions
self.grid=grid self.grid = grid
self.lastpos=[0,0,0,0,0,0,0] self.lastpos = [0, 0, 0, 0, 0, 0, 0]
self.hilightpos=self.lastpos[:] self.hilightpos = self.lastpos[:]
self.Bind(wx.EVT_PAINT,self.paint) self.Bind(wx.EVT_PAINT, self.paint)
self.Bind(wx.EVT_SIZE,self.resize) self.Bind(wx.EVT_SIZE, self.resize)
self.lines={} self.lines = {}
self.pens={} self.pens = {}
self.arcs={} self.arcs = {}
self.arcpens={} self.arcpens = {}
self.layers=[] self.layers = []
self.layerindex=0 self.layerindex = 0
self.filament_width=extrusion_width # set it to 0 to disable scaling lines with zoom self.filament_width = extrusion_width # set it to 0 to disable scaling lines with zoom
self.basescale=[min(float(size[0])/build_dimensions[0],float(size[1])/build_dimensions[1])]*2 self.basescale = [min(float(size[0])/build_dimensions[0], float(size[1])/build_dimensions[1])]*2
self.scale=self.basescale self.scale = self.basescale
penwidth = max(1.0,self.filament_width*((self.scale[0]+self.scale[1])/2.0)) penwidth = max(1.0, self.filament_width*((self.scale[0]+self.scale[1])/2.0))
self.translate=[0.0,0.0] self.translate = [0.0, 0.0]
self.mainpen=wx.Pen(wx.Colour(0,0,0),penwidth) self.mainpen = wx.Pen(wx.Colour(0, 0, 0), penwidth)
self.arcpen=wx.Pen(wx.Colour(255,0,0),penwidth) self.arcpen = wx.Pen(wx.Colour(255, 0, 0), penwidth)
self.travelpen=wx.Pen(wx.Colour(10,80,80),penwidth) self.travelpen = wx.Pen(wx.Colour(10, 80, 80), penwidth)
self.hlpen=wx.Pen(wx.Colour(200,50,50),penwidth) self.hlpen = wx.Pen(wx.Colour(200, 50, 50), penwidth)
self.fades=[wx.Pen(wx.Colour(250-0.6**i*100,250-0.6**i*100,200-0.4**i*50),penwidth) for i in xrange(6)] self.fades = [wx.Pen(wx.Colour(250-0.6**i*100, 250-0.6**i*100, 200-0.4**i*50), penwidth) for i in xrange(6)]
self.penslist=[self.mainpen,self.travelpen,self.hlpen]+self.fades self.penslist = [self.mainpen, self.travelpen, self.hlpen]+self.fades
self.showall=0 self.showall = 0
self.hilight=[] self.hilight = []
self.hilightarcs=[] self.hilightarcs = []
self.dirty=1 self.dirty = 1
self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1) self.blitmap = wx.EmptyBitmap(self.GetClientSize()[0], self.GetClientSize()[1],-1)
def inject(self): def inject(self):
#import pdb; pdb.set_trace() #import pdb; pdb.set_trace()
print"Inject code here..." print"Inject code here..."
print "Layer "+str(self.layerindex +1)+" - Z = "+str(self.layers[self.layerindex])+" mm" print "Layer "+str(self.layerindex +1)+" - Z = "+str(self.layers[self.layerindex])+" mm"
def clear(self): def clear(self):
self.lastpos=[0,0,0,0,0,0,0] self.lastpos = [0, 0, 0, 0, 0, 0, 0]
self.lines={} self.lines = {}
self.pens={} self.pens = {}
self.arcs={} self.arcs = {}
self.arcpens={} self.arcpens = {}
self.layers=[] self.layers = []
self.hilight=[] self.hilight = []
self.hilightarcs=[] self.hilightarcs = []
self.layerindex=0 self.layerindex = 0
self.showall=0 self.showall = 0
self.dirty=1 self.dirty = 1
#self.repaint() #self.repaint()
def layerup(self): def layerup(self):
if(self.layerindex+1<len(self.layers)): if(self.layerindex+1<len(self.layers)):
self.layerindex+=1 self.layerindex+=1
# Display layer info on statusbar (Jezmy) # Display layer info on statusbar (Jezmy)
self.parent.SetStatusText("Layer "+str(self.layerindex +1)+" - Going Up - Z = "+str(self.layers[self.layerindex])+" mm",0) self.parent.SetStatusText("Layer "+str(self.layerindex +1)+" - Going Up - Z = "+str(self.layers[self.layerindex])+" mm", 0)
self.repaint() self.repaint()
self.Refresh() self.Refresh()
def layerdown(self): def layerdown(self):
if(self.layerindex>0): if(self.layerindex>0):
self.layerindex-=1 self.layerindex-=1
# Display layer info on statusbar (Jezmy) # Display layer info on statusbar (Jezmy)
self.parent.SetStatusText("Layer "+str(self.layerindex + 1)+" - Going Down - Z = "+str(self.layers[self.layerindex])+ " mm",0) self.parent.SetStatusText("Layer "+str(self.layerindex + 1)+" - Going Down - Z = "+str(self.layers[self.layerindex])+ " mm", 0)
self.repaint() self.repaint()
self.Refresh() self.Refresh()
def setlayer(self,layer): def setlayer(self, layer):
try: try:
self.layerindex=self.layers.index(layer) self.layerindex = self.layers.index(layer)
self.repaint() self.repaint()
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
self.showall=0 self.showall = 0
except: except:
pass pass
def resize(self,event): def resize(self, event):
size=self.GetClientSize() size = self.GetClientSize()
newsize=min(float(size[0])/self.size[0],float(size[1])/self.size[1]) newsize = min(float(size[0])/self.size[0], float(size[1])/self.size[1])
self.size=self.GetClientSize() self.size = self.GetClientSize()
wx.CallAfter(self.zoom,0,0,newsize) wx.CallAfter(self.zoom, 0, 0, newsize)
def zoom(self,x,y,factor): def zoom(self, x, y, factor):
self.scale = [s * factor for s in self.scale] self.scale = [s * factor for s in self.scale]
self.translate = [ x - (x-self.translate[0]) * factor, self.translate = [ x - (x-self.translate[0]) * factor,
y - (y-self.translate[1]) * factor] y - (y-self.translate[1]) * factor]
penwidth = max(1.0,self.filament_width*((self.scale[0]+self.scale[1])/2.0)) penwidth = max(1.0, self.filament_width*((self.scale[0]+self.scale[1])/2.0))
for pen in self.penslist: for pen in self.penslist:
pen.SetWidth(penwidth) pen.SetWidth(penwidth)
#self.dirty=1 #self.dirty = 1
self.repaint() self.repaint()
self.Refresh() self.Refresh()
def repaint(self): def repaint(self):
self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1) self.blitmap = wx.EmptyBitmap(self.GetClientSize()[0], self.GetClientSize()[1],-1)
dc=wx.MemoryDC() dc = wx.MemoryDC()
dc.SelectObject(self.blitmap) dc.SelectObject(self.blitmap)
dc.SetBackground(wx.Brush((250,250,200))) dc.SetBackground(wx.Brush((250, 250, 200)))
dc.Clear() dc.Clear()
dc.SetPen(wx.Pen(wx.Colour(180,180,150))) dc.SetPen(wx.Pen(wx.Colour(180, 180, 150)))
for grid_unit in self.grid: for grid_unit in self.grid:
if grid_unit > 0: if grid_unit > 0:
for x in xrange(int(self.build_dimensions[0]/grid_unit)+1): for x in xrange(int(self.build_dimensions[0]/grid_unit)+1):
dc.DrawLine(self.translate[0]+x*self.scale[0]*grid_unit,self.translate[1],self.translate[0]+x*self.scale[0]*grid_unit,self.translate[1]+self.scale[1]*self.build_dimensions[1]) dc.DrawLine(self.translate[0]+x*self.scale[0]*grid_unit, self.translate[1], self.translate[0]+x*self.scale[0]*grid_unit, self.translate[1]+self.scale[1]*self.build_dimensions[1])
for y in xrange(int(self.build_dimensions[1]/grid_unit)+1): for y in xrange(int(self.build_dimensions[1]/grid_unit)+1):
dc.DrawLine(self.translate[0],self.translate[1]+y*self.scale[1]*grid_unit,self.translate[0]+self.scale[0]*self.build_dimensions[0],self.translate[1]+y*self.scale[1]*grid_unit) dc.DrawLine(self.translate[0], self.translate[1]+y*self.scale[1]*grid_unit, self.translate[0]+self.scale[0]*self.build_dimensions[0], self.translate[1]+y*self.scale[1]*grid_unit)
dc.SetPen(wx.Pen(wx.Colour(0,0,0))) dc.SetPen(wx.Pen(wx.Colour(0, 0, 0)))
if not self.showall: if not self.showall:
self.size = self.GetSize() self.size = self.GetSize()
dc.SetBrush(wx.Brush((43,144,255))) dc.SetBrush(wx.Brush((43, 144, 255)))
dc.DrawRectangle(self.size[0]-15,0,15,self.size[1]) dc.DrawRectangle(self.size[0]-15, 0, 15, self.size[1])
dc.SetBrush(wx.Brush((0,255,0))) dc.SetBrush(wx.Brush((0, 255, 0)))
if len(self.layers): if len(self.layers):
dc.DrawRectangle(self.size[0]-14,(1.0-(1.0*(self.layerindex+1))/len(self.layers))*self.size[1],13,self.size[1]-1) dc.DrawRectangle(self.size[0]-14, (1.0-(1.0*(self.layerindex+1))/len(self.layers))*self.size[1], 13, self.size[1]-1)
def _drawlines(lines,pens): def _drawlines(lines, pens):
def _scaler(x): def _scaler(x):
return (self.scale[0]*x[0]+self.translate[0], return (self.scale[0]*x[0]+self.translate[0],
self.scale[1]*x[1]+self.translate[1], self.scale[1]*x[1]+self.translate[1],
self.scale[0]*x[2]+self.translate[0], self.scale[0]*x[2]+self.translate[0],
self.scale[1]*x[3]+self.translate[1],) self.scale[1]*x[3]+self.translate[1],)
scaled_lines = map(_scaler,lines) scaled_lines = map(_scaler, lines)
dc.DrawLineList(scaled_lines, pens) dc.DrawLineList(scaled_lines, pens)
def _drawarcs(arcs,pens): def _drawarcs(arcs, pens):
def _scaler(x): def _scaler(x):
return (self.scale[0]*x[0]+self.translate[0], return (self.scale[0]*x[0]+self.translate[0],
self.scale[1]*x[1]+self.translate[1], self.scale[1]*x[1]+self.translate[1],
...@@ -275,61 +275,61 @@ class gviz(wx.Panel): ...@@ -275,61 +275,61 @@ class gviz(wx.Panel):
self.scale[1]*x[3]+self.translate[1], self.scale[1]*x[3]+self.translate[1],
self.scale[0]*x[4]+self.translate[0], self.scale[0]*x[4]+self.translate[0],
self.scale[1]*x[5]+self.translate[1],) self.scale[1]*x[5]+self.translate[1],)
scaled_arcs = map(_scaler,arcs) scaled_arcs = map(_scaler, arcs)
for i in range(len(scaled_arcs)): for i in range(len(scaled_arcs)):
dc.SetPen(pens[i] if type(pens).__name__ == 'list' else pens) dc.SetPen(pens[i] if type(pens).__name__ == 'list' else pens)
dc.SetBrush(wx.TRANSPARENT_BRUSH) dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawArc(*scaled_arcs[i]) dc.DrawArc(*scaled_arcs[i])
if self.showall: if self.showall:
l=[] l = []
for i in self.layers: for i in self.layers:
dc.DrawLineList(l,self.fades[0]) dc.DrawLineList(l, self.fades[0])
_drawlines(self.lines[i], self.pens[i]) _drawlines(self.lines[i], self.pens[i])
_drawarcs(self.arcs[i], self.arcpens[i]) _drawarcs(self.arcs[i], self.arcpens[i])
return return
if self.layerindex<len(self.layers) and self.layers[self.layerindex] in self.lines.keys(): if self.layerindex<len(self.layers) and self.layers[self.layerindex] in self.lines.keys():
for layer_i in xrange(max(0,self.layerindex-6),self.layerindex): for layer_i in xrange(max(0, self.layerindex-6), self.layerindex):
#print i, self.layerindex, self.layerindex-i #print i, self.layerindex, self.layerindex-i
_drawlines(self.lines[self.layers[layer_i]], self.fades[self.layerindex-layer_i-1]) _drawlines(self.lines[self.layers[layer_i]], self.fades[self.layerindex-layer_i-1])
_drawarcs(self.arcs[self.layers[layer_i]], self.fades[self.layerindex-layer_i-1]) _drawarcs(self.arcs[self.layers[layer_i]], self.fades[self.layerindex-layer_i-1])
_drawlines(self.lines[self.layers[self.layerindex]], self.pens[self.layers[self.layerindex]]) _drawlines(self.lines[self.layers[self.layerindex]], self.pens[self.layers[self.layerindex]])
_drawarcs(self.arcs[self.layers[self.layerindex]], self.arcpens[self.layers[self.layerindex]]) _drawarcs(self.arcs[self.layers[self.layerindex]], self.arcpens[self.layers[self.layerindex]])
_drawlines(self.hilight, self.hlpen) _drawlines(self.hilight, self.hlpen)
_drawarcs(self.hilightarcs, self.hlpen) _drawarcs(self.hilightarcs, self.hlpen)
dc.SelectObject(wx.NullBitmap) dc.SelectObject(wx.NullBitmap)
def paint(self,event): def paint(self, event):
dc=wx.PaintDC(self) dc = wx.PaintDC(self)
if(self.dirty): if(self.dirty):
self.repaint() self.repaint()
self.dirty=0 self.dirty = 0
sz=self.GetClientSize() sz = self.GetClientSize()
dc.DrawBitmap(self.blitmap,0,0) dc.DrawBitmap(self.blitmap, 0, 0)
del dc del dc
def addfile(self,gcodes=[]): def addfile(self, gcodes = []):
self.clear() self.clear()
for i in gcodes: for i in gcodes:
self.addgcode(i) self.addgcode(i)
def addgcode(self,gcode="M105",hilight=0): def addgcode(self, gcode = "M105", hilight = 0):
gcode=gcode.split("*")[0] gcode = gcode.split("*")[0]
gcode=gcode.split(";")[0] gcode = gcode.split(";")[0]
gcode = gcode.lower().strip().split() gcode = gcode.lower().strip().split()
if len(gcode) == 0: if len(gcode) == 0:
return return
if gcode[0][0] == 'n': if gcode[0][0] == 'n':
gcode.pop(0) gcode.pop(0)
def _readgcode(): def _readgcode():
target=self.lastpos[:] target = self.lastpos[:]
target[5]=0.0 target[5]=0.0
target[6]=0.0 target[6]=0.0
if hilight: if hilight:
target=self.hilightpos[:] target = self.hilightpos[:]
for i in gcode: for i in gcode:
if i[0]=="x": if i[0]=="x":
target[0]=float(i[1:]) target[0]=float(i[1:])
...@@ -353,14 +353,14 @@ class gviz(wx.Panel): ...@@ -353,14 +353,14 @@ class gviz(wx.Panel):
self.arcpens[target[2]]=[] self.arcpens[target[2]]=[]
self.layers+=[target[2]] self.layers+=[target[2]]
return target return target
def _y(y): def _y(y):
return self.build_dimensions[1]-(y-self.build_dimensions[4]) return self.build_dimensions[1]-(y-self.build_dimensions[4])
def _x(x): def _x(x):
return x-self.build_dimensions[3] return x-self.build_dimensions[3]
start_pos = self.hilightpos[:] if hilight else self.lastpos[:] start_pos = self.hilightpos[:] if hilight else self.lastpos[:]
if gcode[0] in [ "g0", "g1" ]: if gcode[0] in [ "g0", "g1" ]:
target = _readgcode() target = _readgcode()
line = [ _x(start_pos[0]), _y(start_pos[1]), _x(target[0]), _y(target[1]) ] line = [ _x(start_pos[0]), _y(start_pos[1]), _x(target[0]), _y(target[1]) ]
...@@ -372,7 +372,7 @@ class gviz(wx.Panel): ...@@ -372,7 +372,7 @@ class gviz(wx.Panel):
self.hilight += [line] self.hilight += [line]
self.hilightpos = target self.hilightpos = target
self.dirty = 1 self.dirty = 1
if gcode[0] in [ "g2", "g3" ]: if gcode[0] in [ "g2", "g3" ]:
target = _readgcode() target = _readgcode()
arc = [] arc = []
...@@ -381,7 +381,7 @@ class gviz(wx.Panel): ...@@ -381,7 +381,7 @@ class gviz(wx.Panel):
arc += [ _x(start_pos[0] + target[5]), _y(start_pos[1] + target[6]) ] # center arc += [ _x(start_pos[0] + target[5]), _y(start_pos[1] + target[6]) ] # center
if gcode[0] == "g2": # clockwise, reverse endpoints if gcode[0] == "g2": # clockwise, reverse endpoints
arc[0], arc[1], arc[2], arc[3] = arc[2], arc[3], arc[0], arc[1] arc[0], arc[1], arc[2], arc[3] = arc[2], arc[3], arc[0], arc[1]
if not hilight: if not hilight:
self.arcs[ target[2] ] += [arc] self.arcs[ target[2] ] += [arc]
self.arcpens[ target[2] ] += [self.arcpen] self.arcpens[ target[2] ] += [self.arcpen]
...@@ -390,11 +390,10 @@ class gviz(wx.Panel): ...@@ -390,11 +390,10 @@ class gviz(wx.Panel):
self.hilightarcs += [arc] self.hilightarcs += [arc]
self.hilightpos = target self.hilightpos = target
self.dirty = 1 self.dirty = 1
if __name__ == '__main__': if __name__ == '__main__':
app = wx.App(False) app = wx.App(False)
#main = window(open("/home/kliment/designs/spinner/arm_export.gcode")) #main = window(open("/home/kliment/designs/spinner/arm_export.gcode"))
main = window(open("jam.gcode")) main = window(open("jam.gcode"))
main.Show() main.Show()
app.MainLoop() app.MainLoop()
import os import os
import gettext import gettext
# Set up Internationalization using gettext
# searching for installed locales on /usr/share; uses relative folder if not found (windows)
def install_locale(domain): def install_locale(domain):
if os.path.exists('/usr/share/pronterface/locale'): if os.path.exists('/usr/share/pronterface/locale'):
gettext.install(domain, '/usr/share/pronterface/locale', unicode=1) gettext.install(domain, '/usr/share/pronterface/locale', unicode = 1)
elif os.path.exists('/usr/local/share/pronterface/locale'): elif os.path.exists('/usr/local/share/pronterface/locale'):
gettext.install(domain, '/usr/local/share/pronterface/locale', unicode=1) gettext.install(domain, '/usr/local/share/pronterface/locale', unicode = 1)
else: else:
gettext.install(domain, './locale', unicode=1) gettext.install(domain, './locale', unicode = 1)
def imagefile(filename): def imagefile(filename):
for prefix in ['/usr/local/share/pronterface/images', '/usr/share/pronterface/images']: for prefix in ['/usr/local/share/pronterface/images', '/usr/share/pronterface/images']:
candidate = os.path.join(prefix, filename) candidate = os.path.join(prefix, filename)
if os.path.exists(candidate): if os.path.exists(candidate):
return candidate return candidate
local_candidate = os.path.join(os.path.dirname(__file__), "images", filename) local_candidate = os.path.join(os.path.dirname(__file__), "images", filename)
if os.path.exists(local_candidate): if os.path.exists(local_candidate):
return local_candidate return local_candidate
...@@ -22,9 +24,9 @@ def imagefile(filename): ...@@ -22,9 +24,9 @@ def imagefile(filename):
def lookup_file(filename, prefixes): def lookup_file(filename, prefixes):
for prefix in prefixes: for prefix in prefixes:
candidate = os.path.join(prefix, filename) candidate = os.path.join(prefix, filename)
if os.path.exists(candidate): if os.path.exists(candidate):
return candidate return candidate
return filename return filename
def pixmapfile(filename): def pixmapfile(filename):
......
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -21,10 +21,10 @@ import tempfile ...@@ -21,10 +21,10 @@ import tempfile
import shutil import shutil
import svg.document as wxpsvgdocument import svg.document as wxpsvgdocument
import imghdr import imghdr
class dispframe(wx.Frame): class dispframe(wx.Frame):
def __init__(self, parent, title, res=(800, 600), printer=None): def __init__(self, parent, title, res = (800, 600), printer = None):
wx.Frame.__init__(self, parent=parent, title=title) wx.Frame.__init__(self, parent = parent, title = title)
self.p = printer self.p = printer
self.pic = wx.StaticBitmap(self) self.pic = wx.StaticBitmap(self)
self.bitmap = wx.EmptyBitmap(*res) self.bitmap = wx.EmptyBitmap(*res)
...@@ -58,7 +58,7 @@ class dispframe(wx.Frame): ...@@ -58,7 +58,7 @@ class dispframe(wx.Frame):
points = [wx.Point(*map(lambda x:int(round(float(x) * self.scale)), j.strip().split())) for j in i.strip().split("M")[1].split("L")] points = [wx.Point(*map(lambda x:int(round(float(x) * self.scale)), j.strip().split())) for j in i.strip().split("M")[1].split("L")]
dc.DrawPolygon(points, self.size[0] / 2, self.size[1] / 2) dc.DrawPolygon(points, self.size[0] / 2, self.size[1] / 2)
elif self.slicer == 'Slic3r': elif self.slicer == 'Slic3r':
gc = wx.GraphicsContext_Create(dc) gc = wx.GraphicsContext_Create(dc)
gc.Translate(*self.offset) gc.Translate(*self.offset)
gc.Scale(self.scale, self.scale) gc.Scale(self.scale, self.scale)
wxpsvgdocument.SVGDocument(image).render(gc) wxpsvgdocument.SVGDocument(image).render(gc)
...@@ -69,12 +69,12 @@ class dispframe(wx.Frame): ...@@ -69,12 +69,12 @@ class dispframe(wx.Frame):
self.pic.SetBitmap(self.bitmap) self.pic.SetBitmap(self.bitmap)
self.pic.Show() self.pic.Show()
self.Refresh() self.Refresh()
except: except:
raise raise
pass pass
def showimgdelay(self, image): def showimgdelay(self, image):
self.drawlayer(image) self.drawlayer(image)
self.pic.Show() self.pic.Show()
...@@ -82,10 +82,10 @@ class dispframe(wx.Frame): ...@@ -82,10 +82,10 @@ class dispframe(wx.Frame):
self.Refresh() self.Refresh()
if self.p != None and self.p.online: if self.p != None and self.p.online:
self.p.send_now("G91") self.p.send_now("G91")
self.p.send_now("G1 Z%f F300" % (self.thickness,)) self.p.send_now("G1 Z%f F300" % (self.thickness,))
self.p.send_now("G90") self.p.send_now("G90")
def nextimg(self, event): def nextimg(self, event):
if self.index < len(self.layers): if self.index < len(self.layers):
i = self.index i = self.index
...@@ -99,9 +99,9 @@ class dispframe(wx.Frame): ...@@ -99,9 +99,9 @@ class dispframe(wx.Frame):
wx.CallAfter(self.pic.Hide) wx.CallAfter(self.pic.Hide)
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
wx.CallAfter(self.ShowFullScreen, 0) wx.CallAfter(self.ShowFullScreen, 0)
wx.CallAfter(self.timer.Stop) wx.CallAfter(self.timer.Stop)
def present(self, layers, interval=0.5, pause=0.2, thickness=0.4, scale=20, size=(800, 600), offset=(0, 0)): def present(self, layers, interval = 0.5, pause = 0.2, thickness = 0.4, scale = 20, size = (800, 600), offset = (0, 0)):
wx.CallAfter(self.pic.Hide) wx.CallAfter(self.pic.Hide)
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
self.layers = layers self.layers = layers
...@@ -117,58 +117,58 @@ class dispframe(wx.Frame): ...@@ -117,58 +117,58 @@ class dispframe(wx.Frame):
self.timer.Start(1000 * interval + 1000 * pause) self.timer.Start(1000 * interval + 1000 * pause)
class setframe(wx.Frame): class setframe(wx.Frame):
def __init__(self, parent, printer=None): def __init__(self, parent, printer = None):
wx.Frame.__init__(self, parent, title="Projector setup") wx.Frame.__init__(self, parent, title = "Projector setup")
self.f = dispframe(None, "", printer=printer) self.f = dispframe(None, "", printer = printer)
self.panel = wx.Panel(self) self.panel = wx.Panel(self)
self.panel.SetBackgroundColour("orange") self.panel.SetBackgroundColour("orange")
self.bload = wx.Button(self.panel, -1, "Load", pos=(0, 0)) self.bload = wx.Button(self.panel, -1, "Load", pos = (0, 0))
self.bload.Bind(wx.EVT_BUTTON, self.loadfile) self.bload.Bind(wx.EVT_BUTTON, self.loadfile)
wx.StaticText(self.panel, -1, "Layer:", pos=(0, 30)) wx.StaticText(self.panel, -1, "Layer:", pos = (0, 30))
wx.StaticText(self.panel, -1, "mm", pos=(130, 30)) wx.StaticText(self.panel, -1, "mm", pos = (130, 30))
self.thickness = wx.TextCtrl(self.panel, -1, "0.5", pos=(50, 30)) self.thickness = wx.TextCtrl(self.panel, -1, "0.5", pos = (50, 30))
wx.StaticText(self.panel, -1, "Exposure:", pos = (0, 60))
wx.StaticText(self.panel, -1, "s", pos = (130, 60))
self.interval = wx.TextCtrl(self.panel, -1, "0.5", pos = (50, 60))
wx.StaticText(self.panel, -1, "Blank:", pos = (0, 90))
wx.StaticText(self.panel, -1, "s", pos = (130, 90))
self.delay = wx.TextCtrl(self.panel, -1, "0.5", pos = (50, 90))
wx.StaticText(self.panel, -1, "Exposure:", pos=(0, 60)) wx.StaticText(self.panel, -1, "Scale:", pos = (0, 120))
wx.StaticText(self.panel, -1, "s", pos=(130, 60)) wx.StaticText(self.panel, -1, "x", pos = (130, 120))
self.interval = wx.TextCtrl(self.panel, -1, "0.5", pos=(50, 60)) self.scale = wx.TextCtrl(self.panel, -1, "5", pos = (50, 120))
wx.StaticText(self.panel, -1, "Blank:", pos=(0, 90)) wx.StaticText(self.panel, -1, "X:", pos = (160, 30))
wx.StaticText(self.panel, -1, "s", pos=(130, 90)) self.X = wx.TextCtrl(self.panel, -1, "1024", pos = (210, 30))
self.delay = wx.TextCtrl(self.panel, -1, "0.5", pos=(50, 90))
wx.StaticText(self.panel, -1, "Scale:", pos=(0, 120)) wx.StaticText(self.panel, -1, "Y:", pos = (160, 60))
wx.StaticText(self.panel, -1, "x", pos=(130, 120)) self.Y = wx.TextCtrl(self.panel, -1, "768", pos = (210, 60))
self.scale = wx.TextCtrl(self.panel, -1, "5", pos=(50, 120))
wx.StaticText(self.panel, -1, "X:", pos=(160, 30)) wx.StaticText(self.panel, -1, "OffsetX:", pos = (160, 90))
self.X = wx.TextCtrl(self.panel, -1, "1024", pos=(210, 30)) self.offsetX = wx.TextCtrl(self.panel, -1, "50", pos = (210, 90))
wx.StaticText(self.panel, -1, "Y:", pos=(160, 60)) wx.StaticText(self.panel, -1, "OffsetY:", pos = (160, 120))
self.Y = wx.TextCtrl(self.panel, -1, "768", pos=(210, 60)) self.offsetY = wx.TextCtrl(self.panel, -1, "50", pos = (210, 120))
wx.StaticText(self.panel, -1, "OffsetX:", pos=(160, 90))
self.offsetX = wx.TextCtrl(self.panel, -1, "50", pos=(210, 90))
wx.StaticText(self.panel, -1, "OffsetY:", pos=(160, 120)) self.bload = wx.Button(self.panel, -1, "Present", pos = (0, 150))
self.offsetY = wx.TextCtrl(self.panel, -1, "50", pos=(210, 120))
self.bload = wx.Button(self.panel, -1, "Present", pos=(0, 150))
self.bload.Bind(wx.EVT_BUTTON, self.startdisplay) self.bload.Bind(wx.EVT_BUTTON, self.startdisplay)
wx.StaticText(self.panel, -1, "Fullscreen:", pos=(160, 150)) wx.StaticText(self.panel, -1, "Fullscreen:", pos = (160, 150))
self.fullscreen = wx.CheckBox(self.panel, -1, pos=(220, 150)) self.fullscreen = wx.CheckBox(self.panel, -1, pos = (220, 150))
self.fullscreen.SetValue(True) self.fullscreen.SetValue(True)
self.Show() self.Show()
def __del__(self): def __del__(self):
if hasattr(self, 'image_dir') and self.image_dir != '': if hasattr(self, 'image_dir') and self.image_dir != '':
shutil.rmtree(self.image_dir) shutil.rmtree(self.image_dir)
def parsesvg(self, name): def parsesvg(self, name):
et = xml.etree.ElementTree.ElementTree(file=name) et = xml.etree.ElementTree.ElementTree(file = name)
#xml.etree.ElementTree.dump(et) #xml.etree.ElementTree.dump(et)
slicer = 'Slic3r' if et.getroot().find('{http://www.w3.org/2000/svg}metadata') == None else 'Skeinforge' slicer = 'Slic3r' if et.getroot().find('{http://www.w3.org/2000/svg}metadata') == None else 'Skeinforge'
zlast = 0 zlast = 0
...@@ -177,18 +177,18 @@ class setframe(wx.Frame): ...@@ -177,18 +177,18 @@ class setframe(wx.Frame):
if (slicer == 'Slic3r'): if (slicer == 'Slic3r'):
height = et.getroot().get('height') height = et.getroot().get('height')
width = et.getroot().get('width') width = et.getroot().get('width')
for i in et.findall("{http://www.w3.org/2000/svg}g"): for i in et.findall("{http://www.w3.org/2000/svg}g"):
z = float(i.get('{http://slic3r.org/namespaces/slic3r}z')) z = float(i.get('{http://slic3r.org/namespaces/slic3r}z'))
zdiff = z - zlast zdiff = z - zlast
zlast = z zlast = z
svgSnippet = xml.etree.ElementTree.Element('{http://www.w3.org/2000/svg}svg') svgSnippet = xml.etree.ElementTree.Element('{http://www.w3.org/2000/svg}svg')
svgSnippet.set('height', height + 'mm') svgSnippet.set('height', height + 'mm')
svgSnippet.set('width', width + 'mm') svgSnippet.set('width', width + 'mm')
svgSnippet.set('viewBox', '0 0 ' + height + ' ' + width) svgSnippet.set('viewBox', '0 0 ' + height + ' ' + width)
svgSnippet.append(i) svgSnippet.append(i)
ol += [svgSnippet] ol += [svgSnippet]
else : else :
for i in et.findall("{http://www.w3.org/2000/svg}g")[0].findall("{http://www.w3.org/2000/svg}g"): for i in et.findall("{http://www.w3.org/2000/svg}g")[0].findall("{http://www.w3.org/2000/svg}g"):
...@@ -198,7 +198,7 @@ class setframe(wx.Frame): ...@@ -198,7 +198,7 @@ class setframe(wx.Frame):
path = i.find('{http://www.w3.org/2000/svg}path') path = i.find('{http://www.w3.org/2000/svg}path')
ol += [(path.get("d").split("z"))[:-1]] ol += [(path.get("d").split("z"))[:-1]]
return ol, zdiff, slicer return ol, zdiff, slicer
def parse3DLPzip(self, name): def parse3DLPzip(self, name):
if not zipfile.is_zipfile(name): if not zipfile.is_zipfile(name):
raise Exception(name + " is not a zip file!") raise Exception(name + " is not a zip file!")
...@@ -212,9 +212,9 @@ class setframe(wx.Frame): ...@@ -212,9 +212,9 @@ class setframe(wx.Frame):
if os.path.isfile(path) and imghdr.what(path) in acceptedImageTypes: if os.path.isfile(path) and imghdr.what(path) in acceptedImageTypes:
ol.append(wx.Bitmap(path)) ol.append(wx.Bitmap(path))
return ol, -1, "bitmap" return ol, -1, "bitmap"
def loadfile(self, event): def loadfile(self, event):
dlg = wx.FileDialog(self, ("Open file to print"), style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) dlg = wx.FileDialog(self, ("Open file to print"), style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST)
dlg.SetWildcard(("Slic3r or Skeinforge svg files (;*.svg;*.SVG;);3DLP Zip (;*.3dlp.zip;)")) dlg.SetWildcard(("Slic3r or Skeinforge svg files (;*.svg;*.SVG;);3DLP Zip (;*.3dlp.zip;)"))
if(dlg.ShowModal() == wx.ID_OK): if(dlg.ShowModal() == wx.ID_OK):
name = dlg.GetPath() name = dlg.GetPath()
...@@ -240,12 +240,12 @@ class setframe(wx.Frame): ...@@ -240,12 +240,12 @@ class setframe(wx.Frame):
self.f.ShowFullScreen(1) self.f.ShowFullScreen(1)
l = self.layers[0][:] l = self.layers[0][:]
self.f.present(l, self.f.present(l,
thickness=float(self.thickness.GetValue()), thickness = float(self.thickness.GetValue()),
interval=float(self.interval.GetValue()), interval = float(self.interval.GetValue()),
scale=float(self.scale.GetValue()), scale = float(self.scale.GetValue()),
pause=float(self.delay.GetValue()), pause = float(self.delay.GetValue()),
size=(float(self.X.GetValue()), float(self.Y.GetValue())), size = (float(self.X.GetValue()), float(self.Y.GetValue())),
offset=(float(self.offsetX.GetValue()), float(self.offsetY.GetValue()))) offset = (float(self.offsetX.GetValue()), float(self.offsetY.GetValue())))
if __name__ == "__main__": if __name__ == "__main__":
a = wx.App() a = wx.App()
......
# This file is part of the Printrun suite.
#
# Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import wx
class macroed(wx.Dialog):
"""Really simple editor to edit macro definitions"""
def __init__(self, macro_name, definition, callback, gcode = False):
self.indent_chars = " "
title = " macro %s"
if gcode:
title = " %s"
self.gcode = gcode
wx.Dialog.__init__(self, None, title = title % macro_name, style = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
self.callback = callback
self.panel = wx.Panel(self,-1)
titlesizer = wx.BoxSizer(wx.HORIZONTAL)
titletext = wx.StaticText(self.panel,-1, " _") #title%macro_name)
#title.SetFont(wx.Font(11, wx.NORMAL, wx.NORMAL, wx.BOLD))
titlesizer.Add(titletext, 1)
self.findb = wx.Button(self.panel, -1, _("Find"), style = wx.BU_EXACTFIT) #New button for "Find" (Jezmy)
self.findb.Bind(wx.EVT_BUTTON, self.find)
self.okb = wx.Button(self.panel, -1, _("Save"), style = wx.BU_EXACTFIT)
self.okb.Bind(wx.EVT_BUTTON, self.save)
self.Bind(wx.EVT_CLOSE, self.close)
titlesizer.Add(self.findb)
titlesizer.Add(self.okb)
self.cancelb = wx.Button(self.panel, -1, _("Cancel"), style = wx.BU_EXACTFIT)
self.cancelb.Bind(wx.EVT_BUTTON, self.close)
titlesizer.Add(self.cancelb)
topsizer = wx.BoxSizer(wx.VERTICAL)
topsizer.Add(titlesizer, 0, wx.EXPAND)
self.e = wx.TextCtrl(self.panel, style = wx.TE_MULTILINE+wx.HSCROLL, size = (400, 400))
if not self.gcode:
self.e.SetValue(self.unindent(definition))
else:
self.e.SetValue("\n".join(definition))
topsizer.Add(self.e, 1, wx.ALL+wx.EXPAND)
self.panel.SetSizer(topsizer)
topsizer.Layout()
topsizer.Fit(self)
self.Show()
self.e.SetFocus()
def find(self, ev):
# Ask user what to look for, find it and point at it ... (Jezmy)
S = self.e.GetStringSelection()
if not S :
S = "Z"
FindValue = wx.GetTextFromUser('Please enter a search string:', caption = "Search", default_value = S, parent = None)
somecode = self.e.GetValue()
numLines = len(somecode)
position = somecode.find(FindValue, self.e.GetInsertionPoint())
if position == -1 :
# ShowMessage(self,-1, "Not found!")
titletext = wx.TextCtrl(self.panel,-1, "Not Found!")
else:
# self.title.SetValue("Position : "+str(position))
titletext = wx.TextCtrl(self.panel,-1, str(position))
# ananswer = wx.MessageBox(str(numLines)+" Lines detected in file\n"+str(position), "OK")
self.e.SetFocus()
self.e.SetInsertionPoint(position)
self.e.SetSelection(position, position + len(FindValue))
self.e.ShowPosition(position)
def ShowMessage(self, ev , message):
dlg = wxMessageDialog(self, message,
"Info!", wxOK | wxICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
def save(self, ev):
self.Destroy()
if not self.gcode:
self.callback(self.reindent(self.e.GetValue()))
else:
self.callback(self.e.GetValue().split("\n"))
def close(self, ev):
self.Destroy()
if self.webInterface:
webinterface.KillWebInterfaceThread()
def unindent(self, text):
self.indent_chars = text[:len(text)-len(text.lstrip())]
if len(self.indent_chars) == 0:
self.indent_chars = " "
unindented = ""
lines = re.split(r"(?:\r\n?|\n)", text)
#print lines
if len(lines) <= 1:
return text
for line in lines:
if line.startswith(self.indent_chars):
unindented += line[len(self.indent_chars):] + "\n"
else:
unindented += line + "\n"
return unindented
def reindent(self, text):
lines = re.split(r"(?:\r\n?|\n)", text)
if len(lines) <= 1:
return text
reindented = ""
for line in lines:
if line.strip() != "":
reindented += self.indent_chars + line + "\n"
return reindented
class options(wx.Dialog):
"""Options editor"""
def __init__(self, pronterface):
wx.Dialog.__init__(self, None, title = _("Edit settings"), style = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
topsizer = wx.BoxSizer(wx.VERTICAL)
vbox = wx.StaticBoxSizer(wx.StaticBox(self, label = _("Defaults")) ,wx.VERTICAL)
topsizer.Add(vbox, 1, wx.ALL+wx.EXPAND)
grid = wx.FlexGridSizer(rows = 0, cols = 2, hgap = 8, vgap = 2)
grid.SetFlexibleDirection( wx.BOTH )
grid.AddGrowableCol( 1 )
grid.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
vbox.Add(grid, 0, wx.EXPAND)
ctrls = {}
for k, v in sorted(pronterface.settings._all_settings().items()):
ctrls[k, 0] = wx.StaticText(self,-1, k)
ctrls[k, 1] = wx.TextCtrl(self,-1, str(v))
if k in pronterface.helpdict:
ctrls[k, 0].SetToolTipString(pronterface.helpdict.get(k))
ctrls[k, 1].SetToolTipString(pronterface.helpdict.get(k))
grid.Add(ctrls[k, 0], 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.ALIGN_RIGHT)
grid.Add(ctrls[k, 1], 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL|wx.EXPAND)
topsizer.Add(self.CreateSeparatedButtonSizer(wx.OK+wx.CANCEL), 0, wx.EXPAND)
self.SetSizer(topsizer)
topsizer.Layout()
topsizer.Fit(self)
if self.ShowModal() == wx.ID_OK:
for k, v in pronterface.settings._all_settings().items():
if ctrls[k, 1].GetValue() != str(v):
pronterface.set(k, str(ctrls[k, 1].GetValue()))
self.Destroy()
class ButtonEdit(wx.Dialog):
"""Custom button edit dialog"""
def __init__(self, pronterface):
wx.Dialog.__init__(self, None, title = _("Custom button"), style = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
self.pronterface = pronterface
topsizer = wx.BoxSizer(wx.VERTICAL)
grid = wx.FlexGridSizer(rows = 0, cols = 2, hgap = 4, vgap = 2)
grid.AddGrowableCol(1, 1)
grid.Add(wx.StaticText(self,-1, _("Button title")), 0, wx.BOTTOM|wx.RIGHT)
self.name = wx.TextCtrl(self,-1, "")
grid.Add(self.name, 1, wx.EXPAND)
grid.Add(wx.StaticText(self, -1, _("Command")), 0, wx.BOTTOM|wx.RIGHT)
self.command = wx.TextCtrl(self,-1, "")
xbox = wx.BoxSizer(wx.HORIZONTAL)
xbox.Add(self.command, 1, wx.EXPAND)
self.command.Bind(wx.EVT_TEXT, self.macrob_enabler)
self.macrob = wx.Button(self,-1, "..", style = wx.BU_EXACTFIT)
self.macrob.Bind(wx.EVT_BUTTON, self.macrob_handler)
xbox.Add(self.macrob, 0)
grid.Add(xbox, 1, wx.EXPAND)
grid.Add(wx.StaticText(self,-1, _("Color")), 0, wx.BOTTOM|wx.RIGHT)
self.color = wx.TextCtrl(self,-1, "")
grid.Add(self.color, 1, wx.EXPAND)
topsizer.Add(grid, 0, wx.EXPAND)
topsizer.Add( (0, 0), 1)
topsizer.Add(self.CreateStdDialogButtonSizer(wx.OK|wx.CANCEL), 0, wx.ALIGN_CENTER)
self.SetSizer(topsizer)
def macrob_enabler(self, e):
macro = self.command.GetValue()
valid = False
try:
if macro == "":
valid = True
elif self.pronterface.macros.has_key(macro):
valid = True
elif hasattr(self.pronterface.__class__, u"do_"+macro):
valid = False
elif len([c for c in macro if not c.isalnum() and c != "_"]):
valid = False
else:
valid = True
except:
if macro == "":
valid = True
elif self.pronterface.macros.has_key(macro):
valid = True
elif len([c for c in macro if not c.isalnum() and c != "_"]):
valid = False
else:
valid = True
self.macrob.Enable(valid)
def macrob_handler(self, e):
macro = self.command.GetValue()
macro = self.pronterface.edit_macro(macro)
self.command.SetValue(macro)
if self.name.GetValue()=="":
self.name.SetValue(macro)
class TempGauge(wx.Panel):
def __init__(self, parent, size = (200, 22), title = "", maxval = 240, gaugeColour = None):
wx.Panel.__init__(self, parent,-1, size = size)
self.Bind(wx.EVT_PAINT, self.paint)
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
self.width, self.height = size
self.title = title
self.max = maxval
self.gaugeColour = gaugeColour
self.value = 0
self.setpoint = 0
self.recalc()
def recalc(self):
mmax = max(int(self.setpoint*1.05), self.max)
self.scale = float(self.width-2)/float(mmax)
self.ypt = max(16, int(self.scale*max(self.setpoint, self.max/6)))
def SetValue(self, value):
self.value = value
wx.CallAfter(self.Refresh)
def SetTarget(self, value):
self.setpoint = value
self.recalc()
wx.CallAfter(self.Refresh)
def interpolatedColour(self, val, vmin, vmid, vmax, cmin, cmid, cmax):
if val < vmin: return cmin
if val > vmax: return cmax
if val <= vmid:
lo, hi, val, valhi = cmin, cmid, val-vmin, vmid-vmin
else:
lo, hi, val, valhi = cmid, cmax, val-vmid, vmax-vmid
vv = float(val)/valhi
rgb = lo.Red()+(hi.Red()-lo.Red())*vv, lo.Green()+(hi.Green()-lo.Green())*vv, lo.Blue()+(hi.Blue()-lo.Blue())*vv
rgb = map(lambda x:x*0.8, rgb)
return wx.Colour(*map(int, rgb))
def paint(self, ev):
x0, y0, x1, y1, xE, yE = 1, 1, self.ypt+1, 1, self.width+1-2, 20
dc = wx.PaintDC(self)
dc.SetBackground(wx.Brush((255, 255, 255)))
dc.Clear()
cold, medium, hot = wx.Colour(0, 167, 223), wx.Colour(239, 233, 119), wx.Colour(210, 50.100)
gauge1, gauge2 = wx.Colour(255, 255, 210), (self.gaugeColour or wx.Colour(234, 82, 0))
shadow1, shadow2 = wx.Colour(110, 110, 110), wx.Colour(255, 255, 255)
gc = wx.GraphicsContext.Create(dc)
# draw shadow first
# corners
gc.SetBrush(gc.CreateRadialGradientBrush(xE-7, 9, xE-7, 9, 8, shadow1, shadow2))
gc.DrawRectangle(xE-7, 1, 8, 8)
gc.SetBrush(gc.CreateRadialGradientBrush(xE-7, 17, xE-7, 17, 8, shadow1, shadow2))
gc.DrawRectangle(xE-7, 17, 8, 8)
gc.SetBrush(gc.CreateRadialGradientBrush(x0+6, 17, x0+6, 17, 8, shadow1, shadow2))
gc.DrawRectangle(0, 17, x0+6, 8)
# edges
gc.SetBrush(gc.CreateLinearGradientBrush(xE-13, 0, xE-6, 0, shadow1, shadow2))
gc.DrawRectangle(xE-6, 9, 10, 8)
gc.SetBrush(gc.CreateLinearGradientBrush(x0, yE-2, x0, yE+5, shadow1, shadow2))
gc.DrawRectangle(x0+6, yE-2, xE-12, 7)
# draw gauge background
gc.SetBrush(gc.CreateLinearGradientBrush(x0, y0, x1+1, y1, cold, medium))
gc.DrawRoundedRectangle(x0, y0, x1+4, yE, 6)
gc.SetBrush(gc.CreateLinearGradientBrush(x1-2, y1, xE, y1, medium, hot))
gc.DrawRoundedRectangle(x1-2, y1, xE-x1, yE, 6)
# draw gauge
width = 12
w1 = y0+9-width/2
w2 = w1+width
value = x0+max(10, min(self.width+1-2, int(self.value*self.scale)))
#gc.SetBrush(gc.CreateLinearGradientBrush(x0, y0+3, x0, y0+15, gauge1, gauge2))
#gc.SetBrush(gc.CreateLinearGradientBrush(0, 3, 0, 15, wx.Colour(255, 255, 255), wx.Colour(255, 90, 32)))
gc.SetBrush(gc.CreateLinearGradientBrush(x0, y0+3, x0, y0+15, gauge1, self.interpolatedColour(value, x0, x1, xE, cold, medium, hot)))
val_path = gc.CreatePath()
val_path.MoveToPoint(x0, w1)
val_path.AddLineToPoint(value, w1)
val_path.AddLineToPoint(value+2, w1+width/4)
val_path.AddLineToPoint(value+2, w2-width/4)
val_path.AddLineToPoint(value, w2)
#val_path.AddLineToPoint(value-4, 10)
val_path.AddLineToPoint(x0, w2)
gc.DrawPath(val_path)
# draw setpoint markers
setpoint = x0+max(10, int(self.setpoint*self.scale))
gc.SetBrush(gc.CreateBrush(wx.Brush(wx.Colour(0, 0, 0))))
setp_path = gc.CreatePath()
setp_path.MoveToPoint(setpoint-4, y0)
setp_path.AddLineToPoint(setpoint+4, y0)
setp_path.AddLineToPoint(setpoint, y0+5)
setp_path.MoveToPoint(setpoint-4, yE)
setp_path.AddLineToPoint(setpoint+4, yE)
setp_path.AddLineToPoint(setpoint, yE-5)
gc.DrawPath(setp_path)
# draw readout
text = u"T\u00B0 %u/%u"%(self.value, self.setpoint)
#gc.SetFont(gc.CreateFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD), wx.WHITE))
#gc.DrawText(text, 29,-2)
gc.SetFont(gc.CreateFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD), wx.WHITE))
gc.DrawText(self.title, x0+19, y0+4)
gc.DrawText(text, x0+119, y0+4)
gc.SetFont(gc.CreateFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)))
gc.DrawText(self.title, x0+18, y0+3)
gc.DrawText(text, x0+118, y0+3)
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import sys, struct, math import sys, struct, math
def cross(v1,v2): def cross(v1, v2):
return [v1[1]*v2[2]-v1[2]*v2[1],v1[2]*v2[0]-v1[0]*v2[2],v1[0]*v2[1]-v1[1]*v2[0]] return [v1[1]*v2[2]-v1[2]*v2[1], v1[2]*v2[0]-v1[0]*v2[2], v1[0]*v2[1]-v1[1]*v2[0]]
def genfacet(v): def genfacet(v):
veca=[v[1][0]-v[0][0],v[1][1]-v[0][1],v[1][2]-v[0][2]] veca = [v[1][0]-v[0][0], v[1][1]-v[0][1], v[1][2]-v[0][2]]
vecb=[v[2][0]-v[1][0],v[2][1]-v[1][1],v[2][2]-v[1][2]] vecb = [v[2][0]-v[1][0], v[2][1]-v[1][1], v[2][2]-v[1][2]]
vecx=cross(veca,vecb) vecx = cross(veca, vecb)
vlen=math.sqrt(sum(map(lambda x:x*x,vecx))) vlen = math.sqrt(sum(map(lambda x:x*x, vecx)))
if vlen==0: if vlen == 0:
vlen=1 vlen = 1
normal=map(lambda x:x/vlen, vecx) normal = map(lambda x:x/vlen, vecx)
return [normal,v] return [normal, v]
I=[ I = [
[1,0,0,0], [1, 0, 0, 0],
[0,1,0,0], [0, 1, 0, 0],
[0,0,1,0], [0, 0, 1, 0],
[0,0,0,1] [0, 0, 0, 1]
] ]
def transpose(matrix): def transpose(matrix):
return zip(*matrix) return zip(*matrix)
#return [[v[i] for v in matrix] for i in xrange(len(matrix[0]))] #return [[v[i] for v in matrix] for i in xrange(len(matrix[0]))]
def multmatrix(vector,matrix): def multmatrix(vector, matrix):
return map(sum, transpose(map(lambda x:[x[0]*p for p in x[1]], zip(vector, transpose(matrix))))) return map(sum, transpose(map(lambda x:[x[0]*p for p in x[1]], zip(vector, transpose(matrix)))))
def applymatrix(facet,matrix=I): def applymatrix(facet, matrix = I):
#return facet #return facet
#return [map(lambda x:-1.0*x,multmatrix(facet[0]+[1],matrix)[:3]),map(lambda x:multmatrix(x+[1],matrix)[:3],facet[1])] #return [map(lambda x:-1.0*x, multmatrix(facet[0]+[1], matrix)[:3]), map(lambda x:multmatrix(x+[1], matrix)[:3], facet[1])]
return genfacet(map(lambda x:multmatrix(x+[1],matrix)[:3],facet[1])) return genfacet(map(lambda x:multmatrix(x+[1], matrix)[:3], facet[1]))
f=[[0,0,0],[[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565]]] f = [[0, 0, 0],[[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565]]]
m=[ m = [
[1,0,0,0], [1, 0, 0, 0],
[0,1,0,0], [0, 1, 0, 0],
[0,0,1,1], [0, 0, 1, 1],
[0,0,0,1] [0, 0, 0, 1]
] ]
def emitstl(filename,facets=[],objname="stltool_export",binary=1): def emitstl(filename, facets = [], objname = "stltool_export", binary = 1):
if filename is None: if filename is None:
return return
if binary: if binary:
f=open(filename,"wb") f = open(filename, "wb")
buf="".join(["\0"]*80) buf = "".join(["\0"]*80)
buf+=struct.pack("<I",len(facets)) buf+=struct.pack("<I", len(facets))
facetformat=struct.Struct("<ffffffffffffH") facetformat = struct.Struct("<ffffffffffffH")
for i in facets: for i in facets:
l=list(i[0][:]) l = list(i[0][:])
for j in i[1]: for j in i[1]:
l+=j[:] l+=j[:]
l+=[0] l+=[0]
...@@ -73,167 +73,167 @@ def emitstl(filename,facets=[],objname="stltool_export",binary=1): ...@@ -73,167 +73,167 @@ def emitstl(filename,facets=[],objname="stltool_export",binary=1):
f.write(buf) f.write(buf)
f.close() f.close()
return return
f=open(filename,"w")
f = open(filename, "w")
f.write("solid "+objname+"\n") f.write("solid "+objname+"\n")
for i in facets: for i in facets:
f.write(" facet normal "+" ".join(map(str,i[0]))+"\n outer loop\n") f.write(" facet normal "+" ".join(map(str, i[0]))+"\n outer loop\n")
for j in i[1]: for j in i[1]:
f.write(" vertex "+" ".join(map(str,j))+"\n") f.write(" vertex "+" ".join(map(str, j))+"\n")
f.write(" endloop"+"\n") f.write(" endloop"+"\n")
f.write(" endfacet"+"\n") f.write(" endfacet"+"\n")
f.write("endsolid "+objname+"\n") f.write("endsolid "+objname+"\n")
f.close() f.close()
class stl: class stl:
def __init__(self, filename=None): def __init__(self, filename = None):
self.facet=[[0,0,0],[[0,0,0],[0,0,0],[0,0,0]]] self.facet = [[0, 0, 0],[[0, 0, 0],[0, 0, 0],[0, 0, 0]]]
self.facets=[] self.facets = []
self.facetsminz=[] self.facetsminz = []
self.facetsmaxz=[] self.facetsmaxz = []
self.name="" self.name = ""
self.insolid=0 self.insolid = 0
self.infacet=0 self.infacet = 0
self.inloop=0 self.inloop = 0
self.facetloc=0 self.facetloc = 0
if filename is None: if filename is None:
return return
self.f=list(open(filename)) self.f = list(open(filename))
if not self.f[0].startswith("solid"): if not self.f[0].startswith("solid"):
print "Not an ascii stl solid - attempting to parse as binary" print "Not an ascii stl solid - attempting to parse as binary"
f=open(filename,"rb") f = open(filename, "rb")
buf=f.read(84) buf = f.read(84)
while(len(buf)<84): while(len(buf)<84):
newdata=f.read(84-len(buf)) newdata = f.read(84-len(buf))
if not len(newdata): if not len(newdata):
break break
buf+=newdata buf+=newdata
facetcount=struct.unpack_from("<I",buf,80) facetcount = struct.unpack_from("<I", buf, 80)
facetformat=struct.Struct("<ffffffffffffH") facetformat = struct.Struct("<ffffffffffffH")
for i in xrange(facetcount[0]): for i in xrange(facetcount[0]):
buf=f.read(50) buf = f.read(50)
while(len(buf)<50): while(len(buf)<50):
newdata=f.read(50-len(buf)) newdata = f.read(50-len(buf))
if not len(newdata): if not len(newdata):
break break
buf+=newdata buf+=newdata
fd=list(facetformat.unpack(buf)) fd = list(facetformat.unpack(buf))
self.name="binary soloid" self.name = "binary soloid"
self.facet=[fd[:3],[fd[3:6],fd[6:9],fd[9:12]]] self.facet = [fd[:3],[fd[3:6], fd[6:9], fd[9:12]]]
self.facets+=[self.facet] self.facets+=[self.facet]
facet=self.facet facet = self.facet
self.facetsminz+=[(min(map(lambda x:x[2], facet[1])),facet)] self.facetsminz+=[(min(map(lambda x:x[2], facet[1])), facet)]
self.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])),facet)] self.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])), facet)]
f.close() f.close()
return return
for i in self.f: for i in self.f:
if not self.parseline(i): if not self.parseline(i):
return return
def translate(self,v=[0,0,0]): def translate(self, v = [0, 0, 0]):
matrix=[ matrix = [
[1,0,0,v[0]], [1, 0, 0, v[0]],
[0,1,0,v[1]], [0, 1, 0, v[1]],
[0,0,1,v[2]], [0, 0, 1, v[2]],
[0,0,0,1] [0, 0, 0, 1]
] ]
return self.transform(matrix) return self.transform(matrix)
def rotate(self,v=[0,0,0]): def rotate(self, v = [0, 0, 0]):
import math import math
z=v[2] z = v[2]
matrix1=[ matrix1 = [
[math.cos(math.radians(z)),-math.sin(math.radians(z)),0,0], [math.cos(math.radians(z)),-math.sin(math.radians(z)), 0, 0],
[math.sin(math.radians(z)),math.cos(math.radians(z)),0,0], [math.sin(math.radians(z)), math.cos(math.radians(z)), 0, 0],
[0,0,1,0], [0, 0, 1, 0],
[0,0,0,1] [0, 0, 0, 1]
] ]
y=v[0] y = v[0]
matrix2=[ matrix2 = [
[1,0,0,0], [1, 0, 0, 0],
[0,math.cos(math.radians(y)),-math.sin(math.radians(y)),0], [0, math.cos(math.radians(y)),-math.sin(math.radians(y)), 0],
[0,math.sin(math.radians(y)),math.cos(math.radians(y)),0], [0, math.sin(math.radians(y)), math.cos(math.radians(y)), 0],
[0,0,0,1] [0, 0, 0, 1]
] ]
x=v[1] x = v[1]
matrix3=[ matrix3 = [
[math.cos(math.radians(x)),0,-math.sin(math.radians(x)),0], [math.cos(math.radians(x)), 0,-math.sin(math.radians(x)), 0],
[0,1,0,0], [0, 1, 0, 0],
[math.sin(math.radians(x)),0,math.cos(math.radians(x)),0], [math.sin(math.radians(x)), 0, math.cos(math.radians(x)), 0],
[0,0,0,1] [0, 0, 0, 1]
] ]
return self.transform(matrix1).transform(matrix2).transform(matrix3) return self.transform(matrix1).transform(matrix2).transform(matrix3)
def scale(self,v=[0,0,0]): def scale(self, v = [0, 0, 0]):
matrix=[ matrix = [
[v[0],0,0,0], [v[0], 0, 0, 0],
[0,v[1],0,0], [0, v[1], 0, 0],
[0,0,v[2],0], [0, 0, v[2], 0],
[0,0,0,1] [0, 0, 0, 1]
] ]
return self.transform(matrix) return self.transform(matrix)
def transform(self,m=I): def transform(self, m = I):
s=stl() s = stl()
s.facets=[applymatrix(i,m) for i in self.facets] s.facets = [applymatrix(i, m) for i in self.facets]
s.insolid=0 s.insolid = 0
s.infacet=0 s.infacet = 0
s.inloop=0 s.inloop = 0
s.facetloc=0 s.facetloc = 0
s.name=self.name s.name = self.name
for facet in s.facets: for facet in s.facets:
s.facetsminz+=[(min(map(lambda x:x[2], facet[1])),facet)] s.facetsminz+=[(min(map(lambda x:x[2], facet[1])), facet)]
s.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])),facet)] s.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])), facet)]
return s return s
def export(self,f=sys.stdout): def export(self, f = sys.stdout):
f.write("solid "+self.name+"\n") f.write("solid "+self.name+"\n")
for i in self.facets: for i in self.facets:
f.write(" facet normal "+" ".join(map(str,i[0]))+"\n") f.write(" facet normal "+" ".join(map(str, i[0]))+"\n")
f.write(" outer loop"+"\n") f.write(" outer loop"+"\n")
for j in i[1]: for j in i[1]:
f.write(" vertex "+" ".join(map(str,j))+"\n") f.write(" vertex "+" ".join(map(str, j))+"\n")
f.write(" endloop"+"\n") f.write(" endloop"+"\n")
f.write(" endfacet"+"\n") f.write(" endfacet"+"\n")
f.write("endsolid "+self.name+"\n") f.write("endsolid "+self.name+"\n")
f.flush() f.flush()
def parseline(self,l): def parseline(self, l):
l=l.strip() l = l.strip()
if l.startswith("solid"): if l.startswith("solid"):
self.insolid=1 self.insolid = 1
self.name=l[6:] self.name = l[6:]
#print self.name #print self.name
elif l.startswith("endsolid"): elif l.startswith("endsolid"):
self.insolid=0 self.insolid = 0
return 0 return 0
elif l.startswith("facet normal"): elif l.startswith("facet normal"):
l=l.replace(",",".") l = l.replace(", ",".")
self.infacet=11 self.infacet = 11
self.facetloc=0 self.facetloc = 0
self.facet=[[0,0,0],[[0,0,0],[0,0,0],[0,0,0]]] self.facet = [[0, 0, 0],[[0, 0, 0],[0, 0, 0],[0, 0, 0]]]
self.facet[0]=map(float,l.split()[2:]) self.facet[0]=map(float, l.split()[2:])
elif l.startswith("endfacet"): elif l.startswith("endfacet"):
self.infacet=0 self.infacet = 0
self.facets+=[self.facet] self.facets+=[self.facet]
facet=self.facet facet = self.facet
self.facetsminz+=[(min(map(lambda x:x[2], facet[1])),facet)] self.facetsminz+=[(min(map(lambda x:x[2], facet[1])), facet)]
self.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])),facet)] self.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])), facet)]
elif l.startswith("vertex"): elif l.startswith("vertex"):
l=l.replace(",",".") l = l.replace(", ",".")
self.facet[1][self.facetloc]=map(float,l.split()[1:]) self.facet[1][self.facetloc]=map(float, l.split()[1:])
self.facetloc+=1 self.facetloc+=1
return 1 return 1
if __name__=="__main__": if __name__ == "__main__":
s=stl("../../Downloads/frame-vertex-neo-foot-x4.stl") s = stl("../../Downloads/frame-vertex-neo-foot-x4.stl")
for i in xrange(11,11): for i in xrange(11, 11):
working=s.facets[:] working = s.facets[:]
for j in reversed(sorted(s.facetsminz)): for j in reversed(sorted(s.facetsminz)):
if(j[0]>i): if(j[0]>i):
working.remove(j[1]) working.remove(j[1])
...@@ -244,7 +244,7 @@ if __name__=="__main__": ...@@ -244,7 +244,7 @@ if __name__=="__main__":
working.remove(j[1]) working.remove(j[1])
else: else:
break break
print i,len(working) print i, len(working)
emitstl("../../Downloads/frame-vertex-neo-foot-x4-a.stl",s.facets,"emitted_object") emitstl("../../Downloads/frame-vertex-neo-foot-x4-a.stl", s.facets, "emitted_object")
#stl("../prusamendel/stl/mendelplate.stl") #stl("../prusamendel/stl/mendelplate.stl")
#!/usr/bin/python #!/usr/bin/python
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -32,8 +32,8 @@ from pyglet.gl import * ...@@ -32,8 +32,8 @@ from pyglet.gl import *
class GLPanel(wx.Panel): class GLPanel(wx.Panel):
'''A simple class for using OpenGL with wxPython.''' '''A simple class for using OpenGL with wxPython.'''
def __init__(self, parent, id, pos=wx.DefaultPosition, def __init__(self, parent, id, pos = wx.DefaultPosition,
size=wx.DefaultSize, style=0): size = wx.DefaultSize, style = 0):
# Forcing a no full repaint to stop flickering # Forcing a no full repaint to stop flickering
style = style | wx.NO_FULL_REPAINT_ON_RESIZE style = style | wx.NO_FULL_REPAINT_ON_RESIZE
#call super function #call super function
...@@ -46,7 +46,7 @@ class GLPanel(wx.Panel): ...@@ -46,7 +46,7 @@ class GLPanel(wx.Panel):
glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit
# Create the canvas # Create the canvas
self.sizer = wx.BoxSizer(wx.HORIZONTAL) self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.canvas = glcanvas.GLCanvas(self, attribList=attribList) self.canvas = glcanvas.GLCanvas(self, attribList = attribList)
self.sizer.Add(self.canvas, 1, wx.EXPAND) self.sizer.Add(self.canvas, 1, wx.EXPAND)
self.SetSizer(self.sizer) self.SetSizer(self.sizer)
#self.sizer.Fit(self) #self.sizer.Fit(self)
...@@ -215,7 +215,7 @@ class stlview(object): ...@@ -215,7 +215,7 @@ class stlview(object):
normals.extend(i[0]) normals.extend(i[0])
# Create a list of triangle indices. # Create a list of triangle indices.
indices = range(3 * len(facets)) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))] indices = range(3 * len(facets)) # [[3*i, 3*i+1, 3*i+2] for i in xrange(len(facets))]
#print indices[:10] #print indices[:10]
self.vertex_list = batch.add_indexed(len(vertices) // 3, self.vertex_list = batch.add_indexed(len(vertices) // 3,
GL_TRIANGLES, GL_TRIANGLES,
...@@ -233,7 +233,7 @@ def vdiff(v, o): ...@@ -233,7 +233,7 @@ def vdiff(v, o):
class gcview(object): class gcview(object):
def __init__(self, lines, batch, w=0.5, h=0.5): def __init__(self, lines, batch, w = 0.5, h = 0.5):
# Create the vertex and normal arrays. # Create the vertex and normal arrays.
vertices = [] vertices = []
normals = [] normals = []
...@@ -258,7 +258,7 @@ class gcview(object): ...@@ -258,7 +258,7 @@ class gcview(object):
if lasth is not None: if lasth is not None:
self.layers[lasth] = pyglet.graphics.Batch() self.layers[lasth] = pyglet.graphics.Batch()
lt = layertemp[lasth][0] lt = layertemp[lasth][0]
indices = range(len(layertemp[lasth][0]) // 3) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))] indices = range(len(layertemp[lasth][0]) // 3) # [[3*i, 3*i+1, 3*i+2] for i in xrange(len(facets))]
self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3, self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3,
GL_TRIANGLES, GL_TRIANGLES,
None, # group, None, # group,
...@@ -296,7 +296,7 @@ class gcview(object): ...@@ -296,7 +296,7 @@ class gcview(object):
t0 = time.time() t0 = time.time()
# Create a list of triangle indices. # Create a list of triangle indices.
indices = range(3 * 16 * len(lines)) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))] indices = range(3 * 16 * len(lines)) # [[3*i, 3*i+1, 3*i+2] for i in xrange(len(facets))]
self.vlists.append(batch.add_indexed(len(vertices) // 3, self.vlists.append(batch.add_indexed(len(vertices) // 3,
GL_TRIANGLES, GL_TRIANGLES,
None, # group, None, # group,
...@@ -304,14 +304,14 @@ class gcview(object): ...@@ -304,14 +304,14 @@ class gcview(object):
('v3f/static', vertices), ('v3f/static', vertices),
('n3f/static', normals))) ('n3f/static', normals)))
if lasth is not None: if lasth is not None:
self.layers[lasth] = pyglet.graphics.Batch() self.layers[lasth] = pyglet.graphics.Batch()
indices = range(len(layertemp[lasth][0])) # [[3*i,3*i+1,3*i+2] for i in xrange(len(facets))] indices = range(len(layertemp[lasth][0])) # [[3*i, 3*i+1, 3*i+2] for i in xrange(len(facets))]
self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3, self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3,
GL_TRIANGLES, GL_TRIANGLES,
None, # group, None, # group,
indices, indices,
('v3f/static', layertemp[lasth][0]), ('v3f/static', layertemp[lasth][0]),
('n3f/static', layertemp[lasth][1]))) ('n3f/static', layertemp[lasth][1])))
def genline(self, i, h, w): def genline(self, i, h, w):
S = i[0][:3] S = i[0][:3]
...@@ -356,28 +356,28 @@ class gcview(object): ...@@ -356,28 +356,28 @@ class gcview(object):
return spoints, epoints, S, E return spoints, epoints, S, E
def transform(self, line): def transform(self, line):
line = line.split(";")[0] line = line.split(";")[0]
cur = self.prev[:] cur = self.prev[:]
if len(line) > 0: if len(line) > 0:
if "G1" in line or "G0" in line or "G92" in line: if "G1" in line or "G0" in line or "G92" in line:
if("X" in line): if("X" in line):
cur[0] = float(line.split("X")[1].split(" ")[0]) cur[0] = float(line.split("X")[1].split(" ")[0])
if("Y" in line): if("Y" in line):
cur[1] = float(line.split("Y")[1].split(" ")[0]) cur[1] = float(line.split("Y")[1].split(" ")[0])
if("Z" in line): if("Z" in line):
cur[2] = float(line.split("Z")[1].split(" ")[0]) cur[2] = float(line.split("Z")[1].split(" ")[0])
if("E" in line): if("E" in line):
cur[3] = float(line.split("E")[1].split(" ")[0]) cur[3] = float(line.split("E")[1].split(" ")[0])
if self.prev == cur: if self.prev == cur:
return None return None
if self.fline or "G92" in line: if self.fline or "G92" in line:
self.prev = cur self.prev = cur
self.fline = 0 self.fline = 0
return None return None
else: else:
r = [self.prev, cur] r = [self.prev, cur]
self.prev = cur self.prev = cur
return r return r
def delete(self): def delete(self):
for i in self.vlists: for i in self.vlists:
...@@ -466,7 +466,7 @@ def mulquat(q1, rq): ...@@ -466,7 +466,7 @@ def mulquat(q1, rq):
class TestGlPanel(GLPanel): class TestGlPanel(GLPanel):
def __init__(self, parent, size, id=wx.ID_ANY): def __init__(self, parent, size, id = wx.ID_ANY):
super(TestGlPanel, self).__init__(parent, id, wx.DefaultPosition, size, 0) super(TestGlPanel, self).__init__(parent, id, wx.DefaultPosition, size, 0)
self.batches = [] self.batches = []
self.rot = 0 self.rot = 0
...@@ -495,7 +495,7 @@ class TestGlPanel(GLPanel): ...@@ -495,7 +495,7 @@ class TestGlPanel(GLPanel):
def forceresize(self): def forceresize(self):
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1)) self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1))
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] - 1)) self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] - 1))
threading.Thread(target=self.update).start() threading.Thread(target = self.update).start()
self.initialized = 0 self.initialized = 0
def move_shape(self, delta): def move_shape(self, delta):
...@@ -547,7 +547,7 @@ class TestGlPanel(GLPanel): ...@@ -547,7 +547,7 @@ class TestGlPanel(GLPanel):
p1y = -(float(p1[1]) - sz[1] / 2) / (sz[1] / 2) p1y = -(float(p1[1]) - sz[1] / 2) / (sz[1] / 2)
p2x = (float(p2[0]) - sz[0] / 2) / (sz[0] / 2) p2x = (float(p2[0]) - sz[0] / 2) / (sz[0] / 2)
p2y = -(float(p2[1]) - sz[1] / 2) / (sz[1] / 2) p2y = -(float(p2[1]) - sz[1] / 2) / (sz[1] / 2)
#print p1x,p1y,p2x,p2y #print p1x, p1y, p2x, p2y
quat = trackball(p1x, p1y, p2x, p2y, -self.transv[2] / 250.0) quat = trackball(p1x, p1y, p2x, p2y, -self.transv[2] / 250.0)
if self.rot: if self.rot:
self.basequat = mulquat(self.basequat, quat) self.basequat = mulquat(self.basequat, quat)
...@@ -570,27 +570,27 @@ class TestGlPanel(GLPanel): ...@@ -570,27 +570,27 @@ class TestGlPanel(GLPanel):
self.initpos = None self.initpos = None
elif event.Dragging() and event.RightIsDown() and event.ShiftDown(): elif event.Dragging() and event.RightIsDown() and event.ShiftDown():
if self.initpos is None: if self.initpos is None:
self.initpos = event.GetPositionTuple() self.initpos = event.GetPositionTuple()
else: else:
p1 = self.initpos p1 = self.initpos
p2 = event.GetPositionTuple() p2 = event.GetPositionTuple()
sz = self.GetClientSize() sz = self.GetClientSize()
p1 = list(p1) p1 = list(p1)
p2 = list(p2) p2 = list(p2)
p1[1] *= -1 p1[1] *= -1
p2[1] *= -1 p2[1] *= -1
self.transv = map(lambda x, y, z, c: c - self.dist * (x - y) / z, list(p1) + [0], list(p2) + [0], list(sz) + [1], self.transv) self.transv = map(lambda x, y, z, c: c - self.dist * (x - y) / z, list(p1) + [0], list(p2) + [0], list(sz) + [1], self.transv)
glLoadIdentity() glLoadIdentity()
glTranslatef(self.transv[0], self.transv[1], 0) glTranslatef(self.transv[0], self.transv[1], 0)
glTranslatef(0, 0, self.transv[2]) glTranslatef(0, 0, self.transv[2])
if(self.rot): if(self.rot):
glMultMatrixd(build_rotmatrix(self.basequat)) glMultMatrixd(build_rotmatrix(self.basequat))
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat) glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
self.rot = 1 self.rot = 1
self.initpos = None self.initpos = None
else: else:
#mouse is moving without a button press #mouse is moving without a button press
p = event.GetPositionTuple() p = event.GetPositionTuple()
...@@ -710,7 +710,7 @@ class TestGlPanel(GLPanel): ...@@ -710,7 +710,7 @@ class TestGlPanel(GLPanel):
def drawmodel(self, m, n): def drawmodel(self, m, n):
batch = pyglet.graphics.Batch() batch = pyglet.graphics.Batch()
stl = stlview(m.facets, batch=batch) stl = stlview(m.facets, batch = batch)
m.batch = batch m.batch = batch
m.animoffset = 300 m.animoffset = 300
#print m #print m
...@@ -819,8 +819,8 @@ class TestGlPanel(GLPanel): ...@@ -819,8 +819,8 @@ class TestGlPanel(GLPanel):
class GCFrame(wx.Frame): class GCFrame(wx.Frame):
'''A simple class for using OpenGL with wxPython.''' '''A simple class for using OpenGL with wxPython.'''
def __init__(self, parent, ID, title, pos=wx.DefaultPosition, def __init__(self, parent, ID, title, pos = wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE): size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
super(GCFrame, self).__init__(parent, ID, title, pos, (size[0] + 150, size[1]), style) super(GCFrame, self).__init__(parent, ID, title, pos, (size[0] + 150, size[1]), style)
class d: class d:
...@@ -833,21 +833,21 @@ class GCFrame(wx.Frame): ...@@ -833,21 +833,21 @@ class GCFrame(wx.Frame):
m.curlayer = 0.0 m.curlayer = 0.0
m.scale = [1.0, 1.0, 1.0] m.scale = [1.0, 1.0, 1.0]
m.batch = pyglet.graphics.Batch() m.batch = pyglet.graphics.Batch()
m.gc = gcview([], batch=m.batch) m.gc = gcview([], batch = m.batch)
self.models = {"": m} self.models = {"": m}
self.l = d() self.l = d()
self.modelindex = 0 self.modelindex = 0
self.GLPanel1 = TestGlPanel(self, size) self.GLPanel1 = TestGlPanel(self, size)
def addfile(self, gcode=[]): def addfile(self, gcode = []):
self.models[""].gc.delete() self.models[""].gc.delete()
self.models[""].gc = gcview(gcode, batch=self.models[""].batch) self.models[""].gc = gcview(gcode, batch = self.models[""].batch)
def clear(self): def clear(self):
self.models[""].gc.delete() self.models[""].gc.delete()
self.models[""].gc = gcview([], batch=self.models[""].batch) self.models[""].gc = gcview([], batch = self.models[""].batch)
def Show(self, arg=True): def Show(self, arg = True):
wx.Frame.Show(self, arg) wx.Frame.Show(self, arg)
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1)) self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] + 1))
self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] - 1)) self.SetClientSize((self.GetClientSize()[0], self.GetClientSize()[1] - 1))
...@@ -868,10 +868,10 @@ class GCFrame(wx.Frame): ...@@ -868,10 +868,10 @@ class GCFrame(wx.Frame):
def main(): def main():
app = wx.App(redirect=False) app = wx.App(redirect = False)
frame = GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size=(400, 400)) frame = GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size = (400, 400))
frame.addfile(list(open("carriage dump_export.gcode"))) frame.addfile(list(open("carriage dump_export.gcode")))
#frame = wx.Frame(None, -1, "GL Window", size=(400, 400)) #frame = wx.Frame(None, -1, "GL Window", size = (400, 400))
#panel = TestGlPanel(frame) #panel = TestGlPanel(frame)
#frame.Show(True) #frame.Show(True)
#app.MainLoop() #app.MainLoop()
......
...@@ -4,10 +4,10 @@ ...@@ -4,10 +4,10 @@
import wx import wx
def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False): def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise = False):
""" Draws an arc of an ellipse within bounding rect (x,y,w,h) """ Draws an arc of an ellipse within bounding rect (x, y, w, h)
from startArc to endArc (in radians, relative to the horizontal line of the eclipse)""" from startArc to endArc (in radians, relative to the horizontal line of the eclipse)"""
if True: if True:
import warnings import warnings
warnings.warn("elliptical arcs are not supported") warnings.warn("elliptical arcs are not supported")
...@@ -15,7 +15,7 @@ def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False): ...@@ -15,7 +15,7 @@ def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False):
h = h/2.0 h = h/2.0
self.AddArc(x+w, y+h, ((w+h)/2), startAngle, endAngle, clockwise) self.AddArc(x+w, y+h, ((w+h)/2), startAngle, endAngle, clockwise)
return return
else: else:
#implement in terms of AddArc by applying a transformation matrix #implement in terms of AddArc by applying a transformation matrix
#Sigh this can't work, still need to patch wx to allow #Sigh this can't work, still need to patch wx to allow
#either a) AddPath that's not a closed path or #either a) AddPath that's not a closed path or
...@@ -25,19 +25,18 @@ def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False): ...@@ -25,19 +25,18 @@ def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False):
#possibly be simulated by combining the current transform with option a. #possibly be simulated by combining the current transform with option a.
mtx = wx.GraphicsRenderer_GetDefaultRenderer().CreateMatrix() mtx = wx.GraphicsRenderer_GetDefaultRenderer().CreateMatrix()
path = wx.GraphicsRenderer_GetDefaultRenderer().CreatePath() path = wx.GraphicsRenderer_GetDefaultRenderer().CreatePath()
mtx.Translate(x+(w/2.0), y+(h/2.0)) mtx.Translate(x+(w/2.0), y+(h/2.0))
mtx.Scale(w/2.0, y/2.0) mtx.Scale(w/2.0, y/2.0)
path.AddArc(0, 0, 1, startAngle, endAngle, clockwise) path.AddArc(0, 0, 1, startAngle, endAngle, clockwise)
path.Transform(mtx) path.Transform(mtx)
self.AddPath(path) self.AddPath(path)
self.MoveToPoint(path.GetCurrentPoint()) self.MoveToPoint(path.GetCurrentPoint())
self.CloseSubpath() self.CloseSubpath()
if not hasattr(wx.GraphicsPath, "AddEllipticalArc"): if not hasattr(wx.GraphicsPath, "AddEllipticalArc"):
wx.GraphicsPath.AddEllipticalArc = AddEllipticalArc wx.GraphicsPath.AddEllipticalArc = AddEllipticalArc
del AddEllipticalArc del AddEllipticalArc
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Parsers for specific attributes Parsers for specific attributes
""" """
import urlparse import urlparse
from pyparsing import (Literal, from pyparsing import (Literal,
Optional, oneOf, Group, StringEnd, Combine, Word, alphas, hexnums, Optional, oneOf, Group, StringEnd, Combine, Word, alphas, hexnums,
CaselessLiteral, SkipTo CaselessLiteral, SkipTo
) )
...@@ -21,23 +21,23 @@ def parsePossibleURL(t): ...@@ -21,23 +21,23 @@ def parsePossibleURL(t):
colorDeclaration = none | currentColor | colourValue colorDeclaration = none | currentColor | colourValue
urlEnd = ( urlEnd = (
Literal(")").suppress() + Literal(")").suppress() +
Optional(Group(colorDeclaration), default=()) + Optional(Group(colorDeclaration), default = ()) +
StringEnd() StringEnd()
) )
url = ( url = (
CaselessLiteral("URL") CaselessLiteral("URL")
+ +
Literal("(").suppress()+ Literal("(").suppress()+
Group(SkipTo(urlEnd, include=True).setParseAction(parsePossibleURL)) Group(SkipTo(urlEnd, include = True).setParseAction(parsePossibleURL))
) )
#paint value will parse into a (type, details) tuple. #paint value will parse into a (type, details) tuple.
#For none and currentColor, the details tuple will be the empty tuple #For none and currentColor, the details tuple will be the empty tuple
#for CSS color declarations, it will be (type, (R,G,B)) #for CSS color declarations, it will be (type, (R, G, B))
#for URLs, it will be ("URL", ((url tuple), fallback)) #for URLs, it will be ("URL", ((url tuple), fallback))
#The url tuple will be as returned by urlparse.urlsplit, and can be #The url tuple will be as returned by urlparse.urlsplit, and can be
#an empty tuple if the parser has an error #an empty tuple if the parser has an error
#The fallback will be another (type, details) tuple as a parsed #The fallback will be another (type, details) tuple as a parsed
#colorDeclaration, but may be the empty tuple if it is not present #colorDeclaration, but may be the empty tuple if it is not present
......
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
from pyparsing import Literal, Combine from pyparsing import Literal, Combine
from .identifier import identifier from .identifier import identifier
atkeyword = Combine(Literal("@") + identifier) atkeyword = Combine(Literal("@") + identifier)
\ No newline at end of file
...@@ -5,4 +5,3 @@ ...@@ -5,4 +5,3 @@
from pyparsing import nestedExpr from pyparsing import nestedExpr
block = nestedExpr(opener="{", closer="}") block = nestedExpr(opener="{", closer="}")
...@@ -21,31 +21,31 @@ comma = Literal(",").suppress() ...@@ -21,31 +21,31 @@ comma = Literal(",").suppress()
def clampColourByte(val): def clampColourByte(val):
val = int(val) val = int(val)
return min(max(0,val), 255) return min(max(0,val), 255)
def clampColourPerc(val): def clampColourPerc(val):
val = float(val) val = float(val)
return min(max(0,val), 100) return min(max(0,val), 100)
def parseColorPerc(token): def parseColorPerc(token):
val = token[0] val = token[0]
val = clampColourPerc(val) val = clampColourPerc(val)
#normalize to bytes #normalize to bytes
return int(255 * (val / 100.0)) return int(255 * (val / 100.0))
colorByte = Optional(sign) + integerConstant.setParseAction(lambda t: clampColourByte(t[0])) colorByte = Optional(sign) + integerConstant.setParseAction(lambda t: clampColourByte(t[0]))
colorPerc = number.setParseAction(parseColorPerc) + Literal("%").suppress() colorPerc = number.setParseAction(parseColorPerc) + Literal("%").suppress()
rgb = ( rgb = (
Literal("rgb(").setParseAction(lambda t: "RGB") + Literal("rgb(").setParseAction(lambda t: "RGB") +
( (
#integer constants, ie 255,255,255 #integer constants, ie 255,255,255
Group(colorByte + comma + colorByte + comma + colorByte) ^ Group(colorByte + comma + colorByte + comma + colorByte) ^
#percentage values, ie 100%, 50% #percentage values, ie 100%, 50%
Group(colorPerc + comma + colorPerc + comma + colorPerc) Group(colorPerc + comma + colorPerc + comma + colorPerc)
) )
+ +
Literal(")").suppress() + StringEnd() Literal(")").suppress() + StringEnd()
) )
...@@ -54,10 +54,10 @@ def parseShortHex(t): ...@@ -54,10 +54,10 @@ def parseShortHex(t):
doubleHex = Word(hexnums, exact=2).setParseAction(lambda t: int(t[0], 16)) doubleHex = Word(hexnums, exact=2).setParseAction(lambda t: int(t[0], 16))
hexLiteral = (Literal("#").setParseAction(lambda t: "RGB") + hexLiteral = (Literal("#").setParseAction(lambda t: "RGB") +
( (
Group(doubleHex + doubleHex + doubleHex) | Group(doubleHex + doubleHex + doubleHex) |
Word(hexnums, exact=3).setParseAction(parseShortHex) Word(hexnums, exact=3).setParseAction(parseShortHex)
) + StringEnd() ) + StringEnd()
) )
...@@ -66,7 +66,7 @@ def parseNamedColour(t): ...@@ -66,7 +66,7 @@ def parseNamedColour(t):
return ["RGB", NamedColours[t[0].lower()]] return ["RGB", NamedColours[t[0].lower()]]
except KeyError: except KeyError:
return ["RGB", (0,0,0)] return ["RGB", (0,0,0)]
namedColour = Word(alphas).setParseAction(parseNamedColour) namedColour = Word(alphas).setParseAction(parseNamedColour)
...@@ -246,7 +246,7 @@ NamedColours = { ...@@ -246,7 +246,7 @@ NamedColours = {
def fillCSS2SystemColours(): def fillCSS2SystemColours():
#The system colours require a wxApp to be present to retrieve, #The system colours require a wxApp to be present to retrieve,
#so if you wnat support for them you'll need #so if you wnat support for them you'll need
#to call this function after your wxApp instance starts #to call this function after your wxApp instance starts
systemColors = { systemColors = {
"ActiveBorder": wx.SYS_COLOUR_ACTIVEBORDER, "ActiveBorder": wx.SYS_COLOUR_ACTIVEBORDER,
...@@ -280,4 +280,4 @@ def fillCSS2SystemColours(): ...@@ -280,4 +280,4 @@ def fillCSS2SystemColours():
NamedColours.update( NamedColours.update(
#strip the alpha from the system colors. Is this really what we want to do? #strip the alpha from the system colors. Is this really what we want to do?
(k.lower(), wx.SystemSettings.GetColour(v)[:3]) for (k,v) in systemColors.iteritems() (k.lower(), wx.SystemSettings.GetColour(v)[:3]) for (k,v) in systemColors.iteritems()
) )
\ No newline at end of file
...@@ -10,7 +10,7 @@ class White(White): ...@@ -10,7 +10,7 @@ class White(White):
super(White, self).__init__(ws, min, max, exact) super(White, self).__init__(ws, min, max, exact)
escaped = ( escaped = (
Literal("\\").suppress() + Literal("\\").suppress() +
#chr(20)-chr(126) + chr(128)-unichr(sys.maxunicode) #chr(20)-chr(126) + chr(128)-unichr(sys.maxunicode)
Regex(u"[\u0020-\u007e\u0080-\uffff]", re.IGNORECASE) Regex(u"[\u0020-\u007e\u0080-\uffff]", re.IGNORECASE)
) )
...@@ -18,7 +18,7 @@ escaped = ( ...@@ -18,7 +18,7 @@ escaped = (
def convertToUnicode(t): def convertToUnicode(t):
return unichr(int(t[0], 16)) return unichr(int(t[0], 16))
hex_unicode = ( hex_unicode = (
Literal("\\").suppress() + Literal("\\").suppress() +
Regex("[0-9a-f]{1,6}", re.IGNORECASE) + Regex("[0-9a-f]{1,6}", re.IGNORECASE) +
Optional(White(exact=1)).suppress() Optional(White(exact=1)).suppress()
).setParseAction(convertToUnicode) ).setParseAction(convertToUnicode)
...@@ -29,9 +29,9 @@ escape = hex_unicode | escaped ...@@ -29,9 +29,9 @@ escape = hex_unicode | escaped
#any unicode literal outside the 0-127 ascii range #any unicode literal outside the 0-127 ascii range
nonascii = Regex(u"[^\u0000-\u007f]") nonascii = Regex(u"[^\u0000-\u007f]")
#single character for starting an identifier. #single character for starting an identifier.
nmstart = Regex(u"[A-Z]", re.IGNORECASE) | nonascii | escape nmstart = Regex(u"[A-Z]", re.IGNORECASE) | nonascii | escape
nmchar = Regex(u"[0-9A-Z-]", re.IGNORECASE) | nonascii | escape nmchar = Regex(u"[0-9A-Z-]", re.IGNORECASE) | nonascii | escape
identifier = Combine(nmstart + ZeroOrMore(nmchar)) identifier = Combine(nmstart + ZeroOrMore(nmchar))
\ No newline at end of file
...@@ -5,4 +5,4 @@ def inlineStyle(styleString): ...@@ -5,4 +5,4 @@ def inlineStyle(styleString):
return {} return {}
styles = styleString.split(";") styles = styleString.split(";")
rv = dict(style.split(":") for style in styles if len(style) != 0) rv = dict(style.split(":") for style in styles if len(style) != 0)
return rv return rv
\ No newline at end of file
...@@ -48,4 +48,4 @@ transformList = delimitedList(Group(transform), delim=maybeComma) ...@@ -48,4 +48,4 @@ transformList = delimitedList(Group(transform), delim=maybeComma)
if __name__ == '__main__': if __name__ == '__main__':
from tests.test_css import * from tests.test_css import *
unittest.main() unittest.main()
\ No newline at end of file
...@@ -43,4 +43,4 @@ length = lengthValue + Optional(lengthUnit, default=None) + StringEnd() ...@@ -43,4 +43,4 @@ length = lengthValue + Optional(lengthUnit, default=None) + StringEnd()
length.leaveWhitespace() length.leaveWhitespace()
#set the parse action aftward so it doesn't "infect" the parsers that build on it #set the parse action aftward so it doesn't "infect" the parsers that build on it
number.setParseAction(asFloat) number.setParseAction(asFloat)
\ No newline at end of file
...@@ -14,22 +14,22 @@ from svg.css.colour import colourValue ...@@ -14,22 +14,22 @@ from svg.css.colour import colourValue
from svg.css import values from svg.css import values
from attributes import paintValue from attributes import paintValue
document = """<?xml version="1.0" standalone="no"?> document = """<?xml version = "1.0" standalone = "no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="4cm" height="4cm" viewBox="0 0 400 400" <svg width = "4cm" height = "4cm" viewBox = "0 0 400 400"
xmlns="http://www.w3.org/2000/svg" version="1.1"> xmlns = "http://www.w3.org/2000/svg" version = "1.1">
<title>Example triangle01- simple example of a 'path'</title> <title>Example triangle01- simple example of a 'path'</title>
<desc>A path that draws a triangle</desc> <desc>A path that draws a triangle</desc>
<rect x="1" y="1" width="398" height="398" <rect x = "1" y = "1" width = "398" height = "398"
fill="none" stroke="blue" /> fill = "none" stroke = "blue" />
<path d="M 100 100 L 300 100 L 200 300 z" <path d = "M 100 100 L 300 100 L 200 300 z"
fill="red" stroke="blue" stroke-width="3" /> fill = "red" stroke = "blue" stroke-width = "3" />
</svg>""" </svg>"""
makePath = lambda: wx.GraphicsRenderer_GetDefaultRenderer().CreatePath() makePath = lambda: wx.GraphicsRenderer_GetDefaultRenderer().CreatePath()
def attrAsFloat(node, attr, defaultValue="0"): def attrAsFloat(node, attr, defaultValue = "0"):
val = node.get(attr, defaultValue) val = node.get(attr, defaultValue)
#TODO: process stuff like "inherit" by walking back up the nodes #TODO: process stuff like "inherit" by walking back up the nodes
#fast path optimization - if it's a valid float, don't #fast path optimization - if it's a valid float, don't
...@@ -38,8 +38,8 @@ def attrAsFloat(node, attr, defaultValue="0"): ...@@ -38,8 +38,8 @@ def attrAsFloat(node, attr, defaultValue="0"):
return float(val) return float(val)
except ValueError: except ValueError:
return valueToPixels(val) return valueToPixels(val)
def valueToPixels(val, defaultUnits="px"): def valueToPixels(val, defaultUnits = "px"):
#TODO manage default units #TODO manage default units
from pyparsing import ParseException from pyparsing import ParseException
try: try:
...@@ -67,7 +67,7 @@ def pathHandler(func): ...@@ -67,7 +67,7 @@ def pathHandler(func):
ops = self.generatePathOps(path) ops = self.generatePathOps(path)
return path, ops return path, ops
return inner return inner
class SVGDocument(object): class SVGDocument(object):
lastControl = None lastControl = None
...@@ -102,12 +102,12 @@ class SVGDocument(object): ...@@ -102,12 +102,12 @@ class SVGDocument(object):
def state(self): def state(self):
""" Retrieve the current state, without popping""" """ Retrieve the current state, without popping"""
return self.stateStack[-1] return self.stateStack[-1]
def processElement(self, element): def processElement(self, element):
""" Process one element of the XML tree. """ Process one element of the XML tree.
Returns the path representing the node, Returns the path representing the node,
and an operation list for drawing the node. and an operation list for drawing the node.
Parent nodes should return a path (for hittesting), but Parent nodes should return a path (for hittesting), but
no draw operations no draw operations
""" """
...@@ -126,7 +126,7 @@ class SVGDocument(object): ...@@ -126,7 +126,7 @@ class SVGDocument(object):
""" Returns an oplist for transformations. """ Returns an oplist for transformations.
This applies to a node, not the current state because This applies to a node, not the current state because
the transform stack is saved in the wxGraphicsContext. the transform stack is saved in the wxGraphicsContext.
This oplist does *not* include the push/pop state commands This oplist does *not* include the push/pop state commands
""" """
ops = [] ops = []
...@@ -175,21 +175,21 @@ class SVGDocument(object): ...@@ -175,21 +175,21 @@ class SVGDocument(object):
) )
if transform == 'skewX': if transform == 'skewX':
matrix = wx.GraphicsRenderer_GetDefaultRenderer().CreateMatrix( matrix = wx.GraphicsRenderer_GetDefaultRenderer().CreateMatrix(
1,0,math.tan(math.radians(args[0])),1,0,0 1, 0, math.tan(math.radians(args[0])), 1, 0, 0
) )
ops.append( ops.append(
(wx.GraphicsContext.ConcatTransform, (matrix,)) (wx.GraphicsContext.ConcatTransform, (matrix,))
) )
if transform == 'skewY': if transform == 'skewY':
matrix = wx.GraphicsRenderer_GetDefaultRenderer().CreateMatrix( matrix = wx.GraphicsRenderer_GetDefaultRenderer().CreateMatrix(
1,math.tan(math.radians(args[0])),0,1,0,0 1, math.tan(math.radians(args[0])), 0, 1, 0, 0
) )
ops.append( ops.append(
(wx.GraphicsContext.ConcatTransform, (matrix,)) (wx.GraphicsContext.ConcatTransform, (matrix,))
) )
return ops return ops
def addGroupToDocument(self, node): def addGroupToDocument(self, node):
""" For parent elements: push on a state, """ For parent elements: push on a state,
then process all child elements then process all child elements
...@@ -197,7 +197,7 @@ class SVGDocument(object): ...@@ -197,7 +197,7 @@ class SVGDocument(object):
ops = [ ops = [
(wx.GraphicsContext.PushState, ()) (wx.GraphicsContext.PushState, ())
] ]
path = makePath() path = makePath()
ops.extend(self.createTransformOpsFromNode(node)) ops.extend(self.createTransformOpsFromNode(node))
for child in node.getchildren(): for child in node.getchildren():
...@@ -210,7 +210,7 @@ class SVGDocument(object): ...@@ -210,7 +210,7 @@ class SVGDocument(object):
(wx.GraphicsContext.PopState, ()) (wx.GraphicsContext.PopState, ())
) )
return path, ops return path, ops
def getFontFromState(self): def getFontFromState(self):
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
family = self.state.get("font-family") family = self.state.get("font-family")
...@@ -227,11 +227,11 @@ class SVGDocument(object): ...@@ -227,11 +227,11 @@ class SVGDocument(object):
else: else:
font.SetPointSize(int(val)) font.SetPointSize(int(val))
return font return font
def addTextToDocument(self, node): def addTextToDocument(self, node):
x, y = [attrAsFloat(node, attr) for attr in ('x', 'y')] x, y = [attrAsFloat(node, attr) for attr in ('x', 'y')]
def DoDrawText(context, text, x, y, brush=wx.NullGraphicsBrush): def DoDrawText(context, text, x, y, brush = wx.NullGraphicsBrush):
#SVG spec appears to originate text from the bottom #SVG spec appears to originate text from the bottom
#rather than the top as with our API. This function #rather than the top as with our API. This function
#will measure and then re-orient the text as needed. #will measure and then re-orient the text as needed.
...@@ -252,14 +252,14 @@ class SVGDocument(object): ...@@ -252,14 +252,14 @@ class SVGDocument(object):
(DoDrawText, (text, x, y)) (DoDrawText, (text, x, y))
] ]
return None, ops return None, ops
@pathHandler @pathHandler
def addRectToDocument(self, node, path): def addRectToDocument(self, node, path):
x, y, w, h = (attrAsFloat(node, attr) for attr in ['x', 'y', 'width', 'height']) x, y, w, h = (attrAsFloat(node, attr) for attr in ['x', 'y', 'width', 'height'])
rx = node.get('rx') rx = node.get('rx')
ry = node.get('ry') ry = node.get('ry')
if not (w and h): if not (w and h):
path.MoveToPoint(x,y) #keep the current point correct path.MoveToPoint(x, y) #keep the current point correct
return return
if rx or ry: if rx or ry:
if rx and ry: if rx and ry:
...@@ -271,7 +271,7 @@ class SVGDocument(object): ...@@ -271,7 +271,7 @@ class SVGDocument(object):
#value clamping as per spec section 9.2 #value clamping as per spec section 9.2
rx = min(rx, w/2) rx = min(rx, w/2)
ry = min(ry, h/2) ry = min(ry, h/2)
#origin #origin
path.MoveToPoint(x+rx, y) path.MoveToPoint(x+rx, y)
path.AddLineToPoint(x+w-rx, y) path.AddLineToPoint(x+w-rx, y)
...@@ -315,12 +315,12 @@ class SVGDocument(object): ...@@ -315,12 +315,12 @@ class SVGDocument(object):
path.AddRectangle( path.AddRectangle(
x, y, w, h x, y, w, h
) )
@pathHandler @pathHandler
def addCircleToDocument(self, node, path): def addCircleToDocument(self, node, path):
cx, cy, r = [attrAsFloat(node, attr) for attr in ('cx', 'cy', 'r')] cx, cy, r = [attrAsFloat(node, attr) for attr in ('cx', 'cy', 'r')]
path.AddCircle(cx, cy, r) path.AddCircle(cx, cy, r)
@pathHandler @pathHandler
def addEllipseToDocument(self, node, path): def addEllipseToDocument(self, node, path):
cx, cy, rx, ry = [float(node.get(attr, 0)) for attr in ('cx', 'cy', 'rx', 'ry')] cx, cy, rx, ry = [float(node.get(attr, 0)) for attr in ('cx', 'cy', 'rx', 'ry')]
...@@ -332,29 +332,29 @@ class SVGDocument(object): ...@@ -332,29 +332,29 @@ class SVGDocument(object):
x = cx - rx x = cx - rx
y = cy - ry y = cy - ry
path.AddEllipse(x, y, rx*2, ry*2) path.AddEllipse(x, y, rx*2, ry*2)
@pathHandler @pathHandler
def addLineToDocument(self, node, path): def addLineToDocument(self, node, path):
x1, y1, x2, y2 = [attrAsFloat(node, attr) for attr in ('x1', 'y1', 'x2', 'y2')] x1, y1, x2, y2 = [attrAsFloat(node, attr) for attr in ('x1', 'y1', 'x2', 'y2')]
path.MoveToPoint(x1, y1) path.MoveToPoint(x1, y1)
path.AddLineToPoint(x2, y2) path.AddLineToPoint(x2, y2)
@pathHandler @pathHandler
def addPolyLineToDocument(self, node, path): def addPolyLineToDocument(self, node, path):
#translate to pathdata and render that #translate to pathdata and render that
data = "M " + node.get("points") data = "M " + node.get("points")
self.addPathDataToPath(data, path) self.addPathDataToPath(data, path)
@pathHandler @pathHandler
def addPolygonToDocument(self, node, path): def addPolygonToDocument(self, node, path):
#translate to pathdata and render that #translate to pathdata and render that
data = "M " + node.get("points") + " Z" data = "M " + node.get("points") + " Z"
self.addPathDataToPath(data, path) self.addPathDataToPath(data, path)
@pathHandler @pathHandler
def addPathDataToDocument(self, node, path): def addPathDataToDocument(self, node, path):
self.addPathDataToPath(node.get('d', ''), path) self.addPathDataToPath(node.get('d', ''), path)
def addPathDataToPath(self, data, path): def addPathDataToPath(self, data, path):
self.lastControl = None self.lastControl = None
self.lastControlQ = None self.lastControlQ = None
...@@ -364,7 +364,7 @@ class SVGDocument(object): ...@@ -364,7 +364,7 @@ class SVGDocument(object):
form of (command, [list of arguments]). form of (command, [list of arguments]).
We translate that to [(command, args[0]), (command, args[1])] We translate that to [(command, args[0]), (command, args[1])]
via a generator. via a generator.
M is special cased because its subsequent arguments M is special cased because its subsequent arguments
become linetos. become linetos.
""" """
...@@ -388,10 +388,10 @@ class SVGDocument(object): ...@@ -388,10 +388,10 @@ class SVGDocument(object):
#print "parsed in", time.time()-t #print "parsed in", time.time()-t
for stroke in normalizeStrokes(parsed): for stroke in normalizeStrokes(parsed):
self.addStrokeToPath(path, stroke) self.addStrokeToPath(path, stroke)
def generatePathOps(self, path): def generatePathOps(self, path):
""" Look at the current state and generate the """ Look at the current state and generate the
draw operations (fill, stroke, neither) for the path""" draw operations (fill, stroke, neither) for the path"""
ops = [] ops = []
brush = self.getBrushFromState(path) brush = self.getBrushFromState(path)
...@@ -414,7 +414,7 @@ class SVGDocument(object): ...@@ -414,7 +414,7 @@ class SVGDocument(object):
(wx.GraphicsContext.StrokePath, (path,)) (wx.GraphicsContext.StrokePath, (path,))
) )
return ops return ops
def getPenFromState(self): def getPenFromState(self):
pencolour = self.state.get('stroke', 'none') pencolour = self.state.get('stroke', 'none')
if pencolour == 'currentColor': if pencolour == 'currentColor':
...@@ -449,7 +449,7 @@ class SVGDocument(object): ...@@ -449,7 +449,7 @@ class SVGDocument(object):
pen.SetJoin(joinmap.get(self.state.get('stroke-linejoin', None), wx.JOIN_MITER)) pen.SetJoin(joinmap.get(self.state.get('stroke-linejoin', None), wx.JOIN_MITER))
return wx.GraphicsRenderer_GetDefaultRenderer().CreatePen(pen) return wx.GraphicsRenderer_GetDefaultRenderer().CreatePen(pen)
def getBrushFromState(self, path=None): def getBrushFromState(self, path = None):
brushcolour = self.state.get('fill', 'black').strip() brushcolour = self.state.get('fill', 'black').strip()
type, details = paintValue.parseString(brushcolour) type, details = paintValue.parseString(brushcolour)
if type == "URL": if type == "URL":
...@@ -465,51 +465,51 @@ class SVGDocument(object): ...@@ -465,51 +465,51 @@ class SVGDocument(object):
box = path.GetBox() box = path.GetBox()
x, y, w, h = box.Get() x, y, w, h = box.Get()
return wx.GraphicsRenderer.GetDefaultRenderer().CreateLinearGradientBrush( return wx.GraphicsRenderer.GetDefaultRenderer().CreateLinearGradientBrush(
x,y,x+w,y+h,wx.Colour(0,0,255,128), wx.RED x, y, x+w, y+h, wx.Colour(0, 0, 255, 128), wx.RED
) )
elif element.tag == '{http://www.w3.org/2000/svg}radialGradient': elif element.tag == '{http://www.w3.org/2000/svg}radialGradient':
box = path.GetBox() box = path.GetBox()
x, y, w, h = box.Get() x, y, w, h = box.Get()
#print w #print w
mx = wx.GraphicsRenderer.GetDefaultRenderer().CreateMatrix(x,y,w,h) mx = wx.GraphicsRenderer.GetDefaultRenderer().CreateMatrix(x, y, w, h)
cx, cy = mx.TransformPoint(0.5, 0.5) cx, cy = mx.TransformPoint(0.5, 0.5)
fx, fy = cx, cy fx, fy = cx, cy
return wx.GraphicsRenderer.GetDefaultRenderer().CreateRadialGradientBrush( return wx.GraphicsRenderer.GetDefaultRenderer().CreateRadialGradientBrush(
cx,cy, cx, cy,
fx,fy, fx, fy,
(max(w,h))/2, (max(w, h))/2,
wx.Colour(0,0,255,128), wx.RED wx.Colour(0, 0, 255, 128), wx.RED
) )
else: else:
#invlid gradient specified #invlid gradient specified
return wx.NullBrush return wx.NullBrush
r,g,b = 0,0,0 r, g, b = 0, 0, 0
if type == 'CURRENTCOLOR': if type == 'CURRENTCOLOR':
type, details = paintValue.parseString(self.state.get('color', 'none')) type, details = paintValue.parseString(self.state.get('color', 'none'))
if type == 'RGB': if type == 'RGB':
r,g,b = details r, g, b = details
elif type == "NONE": elif type == "NONE":
return wx.NullBrush return wx.NullBrush
opacity = self.state.get('fill-opacity', self.state.get('opacity', '1')) opacity = self.state.get('fill-opacity', self.state.get('opacity', '1'))
opacity = float(opacity) opacity = float(opacity)
opacity = min(max(opacity, 0.0), 1.0) opacity = min(max(opacity, 0.0), 1.0)
a = 255 * opacity a = 255 * opacity
#using try/except block instead of #using try/except block instead of
#just setdefault because the wxBrush and wxColour would #just setdefault because the wxBrush and wxColour would
#be created every time anyway in order to pass them, #be created every time anyway in order to pass them,
#defeating the purpose of the cache #defeating the purpose of the cache
try: try:
return SVGDocument.brushCache[(r,g,b,a)] return SVGDocument.brushCache[(r, g, b, a)]
except KeyError: except KeyError:
return SVGDocument.brushCache.setdefault((r,g,b,a), wx.Brush(wx.Colour(r,g,b,a))) return SVGDocument.brushCache.setdefault((r, g, b, a), wx.Brush(wx.Colour(r, g, b, a)))
def resolveURL(self, urlData): def resolveURL(self, urlData):
""" """
Resolve a URL and return an elementTree Element from it. Resolve a URL and return an elementTree Element from it.
Return None if unresolvable Return None if unresolvable
""" """
scheme, netloc, path, query, fragment = urlData scheme, netloc, path, query, fragment = urlData
if scheme == netloc == path == '': if scheme == netloc == path == '':
...@@ -524,15 +524,15 @@ class SVGDocument(object): ...@@ -524,15 +524,15 @@ class SVGDocument(object):
return None return None
else: else:
return self.resolveRemoteURL(urlData) return self.resolveRemoteURL(urlData)
def resolveRemoteURL(self, url): def resolveRemoteURL(self, url):
return None return None
def addStrokeToPath(self, path, stroke): def addStrokeToPath(self, path, stroke):
""" Given a stroke from a path command """ Given a stroke from a path command
(in the form (command, arguments)) create the path (in the form (command, arguments)) create the path
commands that represent it. commands that represent it.
TODO: break out into (yet another) class/module, TODO: break out into (yet another) class/module,
especially so we can get O(1) dispatch on type? especially so we can get O(1) dispatch on type?
""" """
...@@ -564,17 +564,17 @@ class SVGDocument(object): ...@@ -564,17 +564,17 @@ class SVGDocument(object):
) )
self.lastControl = control2 self.lastControl = control2
path.AddCurveToPoint( path.AddCurveToPoint(
control1, control1,
control2, control2,
endpoint endpoint
) )
#~ cp = path.GetCurrentPoint() #~ cp = path.GetCurrentPoint()
#~ path.AddCircle(c1x, c1y, 5) #~ path.AddCircle(c1x, c1y, 5)
#~ path.AddCircle(c2x, c2y, 3) #~ path.AddCircle(c2x, c2y, 3)
#~ path.AddCircle(x,y, 7) #~ path.AddCircle(x, y, 7)
#~ path.MoveToPoint(cp) #~ path.MoveToPoint(cp)
#~ print "C", control1, control2, endpoint #~ print "C", control1, control2, endpoint
elif type == 'S': elif type == 'S':
#control2, endpoint = arg #control2, endpoint = arg
control2, endpoint = map( control2, endpoint = map(
...@@ -584,15 +584,15 @@ class SVGDocument(object): ...@@ -584,15 +584,15 @@ class SVGDocument(object):
control1 = reflectPoint(self.lastControl, path.GetCurrentPoint()) control1 = reflectPoint(self.lastControl, path.GetCurrentPoint())
else: else:
control1 = path.GetCurrentPoint() control1 = path.GetCurrentPoint()
#~ print "S", self.lastControl,":",control1, control2, endpoint #~ print "S", self.lastControl, ":", control1, control2, endpoint
self.lastControl = control2 self.lastControl = control2
path.AddCurveToPoint( path.AddCurveToPoint(
control1, control1,
control2, control2,
endpoint endpoint
) )
elif type == "Q": elif type == "Q":
(cx, cy), (x,y) = map(normalizePoint, arg) (cx, cy), (x, y) = map(normalizePoint, arg)
self.lastControlQ = (cx, cy) self.lastControlQ = (cx, cy)
path.AddQuadCurveToPoint(cx, cy, x, y) path.AddQuadCurveToPoint(cx, cy, x, y)
elif type == "T": elif type == "T":
...@@ -603,50 +603,50 @@ class SVGDocument(object): ...@@ -603,50 +603,50 @@ class SVGDocument(object):
cx, cy = path.GetCurrentPoint() cx, cy = path.GetCurrentPoint()
self.lastControlQ = (cx, cy) self.lastControlQ = (cx, cy)
path.AddQuadCurveToPoint(cx, cy, x, y) path.AddQuadCurveToPoint(cx, cy, x, y)
elif type == "V": elif type == "V":
_, y = normalizePoint((0, arg)) _, y = normalizePoint((0, arg))
x, _ = path.GetCurrentPoint() x, _ = path.GetCurrentPoint()
path.AddLineToPoint(x,y) path.AddLineToPoint(x, y)
elif type == "H": elif type == "H":
x, _ = normalizePoint((arg, 0)) x, _ = normalizePoint((arg, 0))
_, y = path.GetCurrentPoint() _, y = path.GetCurrentPoint()
path.AddLineToPoint(x,y) path.AddLineToPoint(x, y)
elif type == "A": elif type == "A":
#wxGC currently only supports circular arcs, #wxGC currently only supports circular arcs,
#not eliptical ones #not eliptical ones
( (
(rx, ry), #radii of ellipse (rx, ry), #radii of ellipse
angle, #angle of rotation on the ellipse in degrees angle, #angle of rotation on the ellipse in degrees
(fa, fs), #arc and stroke angle flags (fa, fs), #arc and stroke angle flags
(x, y) #endpoint on the arc (x, y) #endpoint on the arc
) = arg ) = arg
x, y = normalizePoint((x,y)) x, y = normalizePoint((x, y))
cx, cy = path.GetCurrentPoint() cx, cy = path.GetCurrentPoint()
if (cx, cy) == (x, y): if (cx, cy) == (x, y):
return #noop return #noop
if (rx == 0 or ry == 0): if (rx == 0 or ry == 0):
#no radius is effectively a line #no radius is effectively a line
path.AddLineToPoint(x,y) path.AddLineToPoint(x, y)
return return
#find the center point for the ellipse #find the center point for the ellipse
#translation via the angle #translation via the angle
angle = angle % 360 angle = angle % 360
angle = math.radians(angle) angle = math.radians(angle)
#translated endpoint #translated endpoint
xPrime = math.cos(angle) * ((cx-x)/2) xPrime = math.cos(angle) * ((cx-x)/2)
xPrime += math.sin(angle) * ((cx-x)/2) xPrime += math.sin(angle) * ((cx-x)/2)
yPrime = -(math.sin(angle)) * ((cy-y)/2) yPrime = -(math.sin(angle)) * ((cy-y)/2)
yPrime += (math.cos(angle)) * ((cy-y)/2) yPrime += (math.cos(angle)) * ((cy-y)/2)
temp = ((rx**2) * (ry**2)) - ((rx**2) * (yPrime**2)) - ((ry**2) * (xPrime**2)) temp = ((rx**2) * (ry**2)) - ((rx**2) * (yPrime**2)) - ((ry**2) * (xPrime**2))
temp /= ((rx**2) * (yPrime**2)) + ((ry**2)*(xPrime**2)) temp /= ((rx**2) * (yPrime**2)) + ((ry**2)*(xPrime**2))
temp = abs(temp) temp = abs(temp)
...@@ -659,7 +659,7 @@ class SVGDocument(object): ...@@ -659,7 +659,7 @@ class SVGDocument(object):
cyPrime = temp * -((ry * xPrime) / rx) cyPrime = temp * -((ry * xPrime) / rx)
if fa == fs: if fa == fs:
cxPrime, cyPrime = -cxPrime, -cyPrime cxPrime, cyPrime = -cxPrime, -cyPrime
#reflect backwards now for the origin #reflect backwards now for the origin
cnx = math.cos(angle) * cxPrime cnx = math.cos(angle) * cxPrime
cnx += math.sin(angle) * cxPrime cnx += math.sin(angle) * cxPrime
...@@ -667,27 +667,27 @@ class SVGDocument(object): ...@@ -667,27 +667,27 @@ class SVGDocument(object):
cny += (math.cos(angle)) * cyPrime cny += (math.cos(angle)) * cyPrime
cnx += ((cx+x)/2.0) cnx += ((cx+x)/2.0)
cny += ((cy+y)/2.0) cny += ((cy+y)/2.0)
#calculate the angle between the two endpoints #calculate the angle between the two endpoints
lastArc = wx.Point2D(x-cnx, y-cny).GetVectorAngle() lastArc = wx.Point2D(x-cnx, y-cny).GetVectorAngle()
firstArc = wx.Point2D(cx-cnx, cy-cny).GetVectorAngle() firstArc = wx.Point2D(cx-cnx, cy-cny).GetVectorAngle()
lastArc = math.radians(lastArc) lastArc = math.radians(lastArc)
firstArc = math.radians(firstArc) firstArc = math.radians(firstArc)
#aargh buggines. #aargh buggines.
#AddArc draws a straight line between #AddArc draws a straight line between
#the endpoints of the arc. #the endpoints of the arc.
#putting it in a subpath makes the strokes come out #putting it in a subpath makes the strokes come out
#correctly, but it still only fills the slice #correctly, but it still only fills the slice
#taking out the MoveToPoint fills correctly. #taking out the MoveToPoint fills correctly.
path.AddEllipse(cnx-rx, cny-ry, rx*2, ry*2) path.AddEllipse(cnx-rx, cny-ry, rx*2, ry*2)
path.MoveToPoint(x, y) path.MoveToPoint(x, y)
#~ npath = makePath() #~ npath = makePath()
#~ npath.AddEllipticalArc(cnx-rx, cny-ry, rx*2, ry*2, firstArc, lastArc, False) #~ npath.AddEllipticalArc(cnx-rx, cny-ry, rx*2, ry*2, firstArc, lastArc, False)
#~ npath.MoveToPoint(x,y) #~ npath.MoveToPoint(x, y)
#~ path.AddPath(npath) #~ path.AddPath(npath)
elif type == 'Z': elif type == 'Z':
#~ Bugginess: #~ Bugginess:
#~ CloseSubpath() doesn't change the #~ CloseSubpath() doesn't change the
...@@ -699,17 +699,17 @@ class SVGDocument(object): ...@@ -699,17 +699,17 @@ class SVGDocument(object):
#~ results #~ results
#~ Manually closing the path *and* calling CloseSubpath() appears #~ Manually closing the path *and* calling CloseSubpath() appears
#~ to give correct results on win32 #~ to give correct results on win32
pt = self.firstPoints.pop() pt = self.firstPoints.pop()
path.AddLineToPoint(pt) path.AddLineToPoint(pt)
path.CloseSubpath() path.CloseSubpath()
def render(self, context): def render(self, context):
if not hasattr(self, "ops"): if not hasattr(self, "ops"):
return return
for op, args in self.ops: for op, args in self.ops:
op(context, *args) op(context, *args)
if __name__ == '__main__': if __name__ == '__main__':
from tests.test_document import * from tests.test_document import *
unittest.main() unittest.main()
""" """
SVG path data parser SVG path data parser
Usage: Usage:
steps = svg.parseString(pathdata) steps = svg.parseString(pathdata)
for command, arguments in steps: for command, arguments in steps:
pass pass
""" """
from pyparsing import (ParserElement, Literal, Word, CaselessLiteral, from pyparsing import (ParserElement, Literal, Word, CaselessLiteral,
Optional, Combine, Forward, ZeroOrMore, nums, oneOf, Group, ParseException, OneOrMore) Optional, Combine, Forward, ZeroOrMore, nums, oneOf, Group, ParseException, OneOrMore)
#ParserElement.enablePackrat() #ParserElement.enablePackrat()
def Command(char): def Command(char):
""" Case insensitive but case preserving""" """ Case insensitive but case preserving"""
return CaselessPreservingLiteral(char) return CaselessPreservingLiteral(char)
def Arguments(token): def Arguments(token):
return Group(token) return Group(token)
class CaselessPreservingLiteral(CaselessLiteral): class CaselessPreservingLiteral(CaselessLiteral):
""" Like CaselessLiteral, but returns the match as found """ Like CaselessLiteral, but returns the match as found
instead of as defined. instead of as defined.
""" """
def __init__( self, matchString ): def __init__( self, matchString ):
super(CaselessPreservingLiteral,self).__init__( matchString.upper() ) super(CaselessPreservingLiteral, self).__init__( matchString.upper() )
self.name = "'%s'" % matchString self.name = "'%s'" % matchString
self.errmsg = "Expected " + self.name self.errmsg = "Expected " + self.name
self.myException.msg = self.errmsg self.myException.msg = self.errmsg
def parseImpl( self, instring, loc, doActions=True ): def parseImpl( self, instring, loc, doActions = True ):
test = instring[ loc:loc+self.matchLen ] test = instring[ loc:loc+self.matchLen ]
if test.upper() == self.match: if test.upper() == self.match:
return loc+self.matchLen, test return loc+self.matchLen, test
...@@ -40,8 +40,8 @@ class CaselessPreservingLiteral(CaselessLiteral): ...@@ -40,8 +40,8 @@ class CaselessPreservingLiteral(CaselessLiteral):
exc = self.myException exc = self.myException
exc.loc = loc exc.loc = loc
exc.pstr = instring exc.pstr = instring
raise exc raise exc
def Sequence(token): def Sequence(token):
""" A sequence of the token""" """ A sequence of the token"""
return OneOrMore(token+maybeComma) return OneOrMore(token+maybeComma)
...@@ -58,13 +58,13 @@ def convertToFloat(s, loc, toks): ...@@ -58,13 +58,13 @@ def convertToFloat(s, loc, toks):
exponent = CaselessLiteral("e")+Optional(sign)+Word(nums) exponent = CaselessLiteral("e")+Optional(sign)+Word(nums)
#note that almost all these fields are optional, #note that almost all these fields are optional,
#and this can match almost anything. We rely on Pythons built-in #and this can match almost anything. We rely on Pythons built-in
#float() function to clear out invalid values - loosely matching like this #float() function to clear out invalid values - loosely matching like this
#speeds up parsing quite a lot #speeds up parsing quite a lot
floatingPointConstant = Combine( floatingPointConstant = Combine(
Optional(sign) + Optional(sign) +
Optional(Word(nums)) + Optional(Word(nums)) +
Optional(Literal(".") + Optional(Word(nums)))+ Optional(Literal(".") + Optional(Word(nums)))+
Optional(exponent) Optional(exponent)
) )
...@@ -75,7 +75,7 @@ number = floatingPointConstant ...@@ -75,7 +75,7 @@ number = floatingPointConstant
#same as FP constant but don't allow a - sign #same as FP constant but don't allow a - sign
nonnegativeNumber = Combine( nonnegativeNumber = Combine(
Optional(Word(nums)) + Optional(Word(nums)) +
Optional(Literal(".") + Optional(Word(nums)))+ Optional(Literal(".") + Optional(Word(nums)))+
Optional(exponent) Optional(exponent)
) )
...@@ -117,10 +117,10 @@ ellipticalArcArgument = Group( ...@@ -117,10 +117,10 @@ ellipticalArcArgument = Group(
arcRadius + maybeComma + #rx, ry arcRadius + maybeComma + #rx, ry
number + maybeComma +#rotation number + maybeComma +#rotation
arcFlags + #large-arc-flag, sweep-flag arcFlags + #large-arc-flag, sweep-flag
coordinatePair #(x,y) coordinatePair #(x, y)
) )
ellipticalArc = Group(Command("A") + Arguments(Sequence(ellipticalArcArgument))) ellipticalArc = Group(Command("A") + Arguments(Sequence(ellipticalArcArgument)))
smoothQuadraticBezierCurveto = Group(Command("T") + Arguments(coordinatePairSequence)) smoothQuadraticBezierCurveto = Group(Command("T") + Arguments(coordinatePairSequence))
...@@ -155,39 +155,37 @@ def profile(): ...@@ -155,39 +155,37 @@ def profile():
p.disable() p.disable()
p.print_stats() p.print_stats()
bpath = """M204.33 139.83 C196.33 133.33 206.68 132.82 206.58 132.58 C192.33 97.08 169.35 bpath = """M204.33 139.83 C196.33 133.33 206.68 132.82 206.58 132.58 C192.33 97.08 169.35
81.41 167.58 80.58 C162.12 78.02 159.48 78.26 160.45 76.97 C161.41 75.68 167.72 79.72 168.58 81.41 167.58 80.58 C162.12 78.02 159.48 78.26 160.45 76.97 C161.41 75.68 167.72 79.72 168.58
80.33 C193.83 98.33 207.58 132.33 207.58 132.33 C207.58 132.33 209.33 133.33 209.58 132.58 80.33 C193.83 98.33 207.58 132.33 207.58 132.33 C207.58 132.33 209.33 133.33 209.58 132.58
C219.58 103.08 239.58 87.58 246.33 81.33 C253.08 75.08 256.63 74.47 247.33 81.58 C218.58 103.58 C219.58 103.08 239.58 87.58 246.33 81.33 C253.08 75.08 256.63 74.47 247.33 81.58 C218.58 103.58
210.34 132.23 210.83 132.33 C222.33 134.83 211.33 140.33 211.83 139.83 C214.85 136.81 214.83 145.83 214.83 210.34 132.23 210.83 132.33 C222.33 134.83 211.33 140.33 211.83 139.83 C214.85 136.81 214.83 145.83 214.83
145.83 C214.83 145.83 231.83 110.83 298.33 66.33 C302.43 63.59 445.83 -14.67 395.83 80.83 C393.24 85.79 375.83 145.83 C214.83 145.83 231.83 110.83 298.33 66.33 C302.43 63.59 445.83 -14.67 395.83 80.83 C393.24 85.79 375.83
105.83 375.83 105.83 C375.83 105.83 377.33 114.33 371.33 121.33 C370.3 122.53 367.83 134.33 361.83 140.83 C360.14 142.67 105.83 375.83 105.83 C375.83 105.83 377.33 114.33 371.33 121.33 C370.3 122.53 367.83 134.33 361.83 140.83 C360.14 142.67
361.81 139.25 361.83 140.83 C362.33 170.83 337.76 170.17 339.33 170.33 C348.83 171.33 350.19 183.66 350.33 183.83 C355.83 361.81 139.25 361.83 140.83 C362.33 170.83 337.76 170.17 339.33 170.33 C348.83 171.33 350.19 183.66 350.33 183.83 C355.83
190.33 353.83 191.83 355.83 194.83 C366.63 211.02 355.24 210.05 356.83 212.83 C360.83 219.83 355.99 222.72 357.33 224.83 190.33 353.83 191.83 355.83 194.83 C366.63 211.02 355.24 210.05 356.83 212.83 C360.83 219.83 355.99 222.72 357.33 224.83
C360.83 230.33 354.75 233.84 354.83 235.33 C355.33 243.83 349.67 240.73 349.83 244.33 C350.33 255.33 346.33 250.83 343.83 254.83 C360.83 230.33 354.75 233.84 354.83 235.33 C355.33 243.83 349.67 240.73 349.83 244.33 C350.33 255.33 346.33 250.83 343.83 254.83
C336.33 266.83 333.46 262.38 332.83 263.83 C329.83 270.83 325.81 269.15 324.33 270.83 C320.83 274.83 317.33 274.83 315.83 276.33 C336.33 266.83 333.46 262.38 332.83 263.83 C329.83 270.83 325.81 269.15 324.33 270.83 C320.83 274.83 317.33 274.83 315.83 276.33
C308.83 283.33 304.86 278.39 303.83 278.83 C287.83 285.83 280.33 280.17 277.83 280.33 C270.33 280.83 271.48 279.67 269.33 277.83 C308.83 283.33 304.86 278.39 303.83 278.83 C287.83 285.83 280.33 280.17 277.83 280.33 C270.33 280.83 271.48 279.67 269.33 277.83
C237.83 250.83 219.33 211.83 215.83 206.83 C214.4 204.79 211.35 193.12 212.33 195.83 C214.33 201.33 213.33 250.33 207.83 250.33 C237.83 250.83 219.33 211.83 215.83 206.83 C214.4 204.79 211.35 193.12 212.33 195.83 C214.33 201.33 213.33 250.33 207.83 250.33
C202.33 250.33 201.83 204.33 205.33 195.83 C206.43 193.16 204.4 203.72 201.79 206.83 C196.33 213.33 179.5 250.83 147.59 277.83 C202.33 250.33 201.83 204.33 205.33 195.83 C206.43 193.16 204.4 203.72 201.79 206.83 C196.33 213.33 179.5 250.83 147.59 277.83
C145.42 279.67 146.58 280.83 138.98 280.33 C136.46 280.17 128.85 285.83 112.65 278.83 C111.61 278.39 107.58 283.33 100.49 276.33 C145.42 279.67 146.58 280.83 138.98 280.33 C136.46 280.17 128.85 285.83 112.65 278.83 C111.61 278.39 107.58 283.33 100.49 276.33
C98.97 274.83 95.43 274.83 91.88 270.83 C90.39 269.15 86.31 270.83 83.27 263.83 C82.64 262.38 79.73 266.83 72.13 254.83 C69.6 250.83 C98.97 274.83 95.43 274.83 91.88 270.83 C90.39 269.15 86.31 270.83 83.27 263.83 C82.64 262.38 79.73 266.83 72.13 254.83 C69.6 250.83
65.54 255.33 66.05 244.33 C66.22 240.73 60.48 243.83 60.99 235.33 C61.08 233.84 54.91 230.33 58.45 224.83 C59.81 222.72 54.91 219.83 65.54 255.33 66.05 244.33 C66.22 240.73 60.48 243.83 60.99 235.33 C61.08 233.84 54.91 230.33 58.45 224.83 C59.81 222.72 54.91 219.83
58.96 212.83 C60.57 210.05 49.04 211.02 59.97 194.83 C62 191.83 59.97 190.33 65.54 183.83 C65.69 183.66 67.06 171.33 76.69 170.33 58.96 212.83 C60.57 210.05 49.04 211.02 59.97 194.83 C62 191.83 59.97 190.33 65.54 183.83 C65.69 183.66 67.06 171.33 76.69 170.33
C78.28 170.17 53.39 170.83 53.9 140.83 C53.92 139.25 55.61 142.67 53.9 140.83 C47.82 134.33 45.32 122.53 44.27 121.33 C38.19 114.33 C78.28 170.17 53.39 170.83 53.9 140.83 C53.92 139.25 55.61 142.67 53.9 140.83 C47.82 134.33 45.32 122.53 44.27 121.33 C38.19 114.33
39.71 105.83 39.71 105.83 C39.71 105.83 22.08 85.79 19.46 80.83 C-31.19 -14.67 114.07 63.59 118.22 66.33 C185.58 110.83 202 145.83 39.71 105.83 39.71 105.83 C39.71 105.83 22.08 85.79 19.46 80.83 C-31.19 -14.67 114.07 63.59 118.22 66.33 C185.58 110.83 202 145.83
202 145.83 C202 145.83 202.36 143.28 203 141.83 C203.64 140.39 204.56 140.02 204.33 139.83 z""" 202 145.83 C202 145.83 202.36 143.28 203 141.83 C203.64 140.39 204.56 140.02 204.33 139.83 z"""
def ptest(): def ptest():
svg.parseString(bpath) svg.parseString(bpath)
if __name__ == '__main__': if __name__ == '__main__':
#~ from tests.test_pathdata import * #~ from tests.test_pathdata import *
#~ unittest.main() #~ unittest.main()
profile() profile()
...@@ -8,11 +8,11 @@ from printrun.printrun_utils import configfile, imagefile, sharedfile ...@@ -8,11 +8,11 @@ from printrun.printrun_utils import configfile, imagefile, sharedfile
users = {} users = {}
def PrintHeader(): def PrintHeader():
return '<html>\n<head>\n<title>Pronterface-Web</title>\n<link rel="stylesheet" type="text/css" href="/css/style.css" type="text/css"></link>\n</head>\n<body>\n' return '<html>\n<head>\n<title>Pronterface-Web</title>\n<link rel = "stylesheet" type = "text/css" href = "/css/style.css" type = "text/css"></link>\n</head>\n<body>\n'
def PrintMenu(): def PrintMenu():
return '<div id="mainmenu"><ul><li><a href="/">home</a></li><li><a href="/settings">settings</a></li><li><a href="/console">console</a></li><li><a href="/status">status (XML)</a></li></ul></div>' return '<div id = "mainmenu"><ul><li><a href = "/">home</a></li><li><a href = "/settings">settings</a></li><li><a href = "/console">console</a></li><li><a href = "/status">status (XML)</a></li></ul></div>'
def PrintFooter(): def PrintFooter():
return "</body></html>" return "</body></html>"
...@@ -24,47 +24,47 @@ def TReloadPage(action): ...@@ -24,47 +24,47 @@ def TReloadPage(action):
def clear_text(mypass): def clear_text(mypass):
return mypass return mypass
gPronterPtr = 0 gPronterPtr = 0
gWeblog = "" gWeblog = ""
gLogRefresh =5 gLogRefresh =5
class SettingsPage(object): class SettingsPage(object):
def __init__(self): def __init__(self):
self.name="<div id='title'>Pronterface Settings</div>" self.name = "<div id='title'>Pronterface Settings</div>"
def index(self): def index(self):
pageText=PrintHeader()+self.name+PrintMenu() pageText = PrintHeader()+self.name+PrintMenu()
pageText=pageText+"<div id='settings'><table>\n<tr><th>setting</th><th>value</th>" pageText = pageText+"<div id='settings'><table>\n<tr><th>setting</th><th>value</th>"
pageText=pageText+"<tr>\n <td><b>Build Dimenstions</b></td><td>"+str(gPronterPtr.settings.build_dimensions)+"</td>\n</tr>" pageText = pageText+"<tr>\n <td><b>Build Dimenstions</b></td><td>"+str(gPronterPtr.settings.build_dimensions)+"</td>\n</tr>"
pageText=pageText+" <tr>\n <td><b>Last Bed Temp</b></td><td>"+str(gPronterPtr.settings.last_bed_temperature)+"</td>\n</tr>" pageText = pageText+" <tr>\n <td><b>Last Bed Temp</b></td><td>"+str(gPronterPtr.settings.last_bed_temperature)+"</td>\n</tr>"
pageText=pageText+" <tr>\n <td><b>Last File Path</b></td><td>"+gPronterPtr.settings.last_file_path+"</td>\n</tr>" pageText = pageText+" <tr>\n <td><b>Last File Path</b></td><td>"+gPronterPtr.settings.last_file_path+"</td>\n</tr>"
pageText=pageText+" <tr>\n <td><b>Last Temperature</b></td><td>"+str(gPronterPtr.settings.last_temperature)+"</td>\n</tr>" pageText = pageText+" <tr>\n <td><b>Last Temperature</b></td><td>"+str(gPronterPtr.settings.last_temperature)+"</td>\n</tr>"
pageText=pageText+" <tr>\n <td><b>Preview Extrusion Width</b></td><td>"+str(gPronterPtr.settings.preview_extrusion_width)+"</td>\n</tr>" pageText = pageText+" <tr>\n <td><b>Preview Extrusion Width</b></td><td>"+str(gPronterPtr.settings.preview_extrusion_width)+"</td>\n</tr>"
pageText=pageText+" <tr>\n <td><b>Filename</b></td><td>"+str(gPronterPtr.filename)+"</td></tr></div>" pageText = pageText+" <tr>\n <td><b>Filename</b></td><td>"+str(gPronterPtr.filename)+"</td></tr></div>"
pageText=pageText+PrintFooter() pageText = pageText+PrintFooter()
return pageText return pageText
index.exposed = True index.exposed = True
class LogPage(object): class LogPage(object):
def __init__(self): def __init__(self):
self.name="<div id='title'>Pronterface Console</div>" self.name = "<div id='title'>Pronterface Console</div>"
def index(self): def index(self):
pageText="<html><head><meta http-equiv='refresh' content='"+str(gLogRefresh)+"'></head><body>" pageText = "<html><head><meta http-equiv='refresh' content='"+str(gLogRefresh)+"'></head><body>"
pageText+="<div id='status'>" pageText+="<div id='status'>"
pageText+=gPronterPtr.status.GetStatusText() pageText+=gPronterPtr.status.GetStatusText()
pageText+="</div>" pageText+="</div>"
pageText=pageText+"<div id='console'>"+gWeblog+"</div>" pageText = pageText+"<div id='console'>"+gWeblog+"</div>"
pageText=pageText+"</body></html>" pageText = pageText+"</body></html>"
return pageText return pageText
index.exposed = True index.exposed = True
class ConsolePage(object): class ConsolePage(object):
def __init__(self): def __init__(self):
self.name="<div id='title'>Pronterface Settings</div>" self.name = "<div id='title'>Pronterface Settings</div>"
def index(self): def index(self):
pageText=PrintHeader()+self.name+PrintMenu() pageText = PrintHeader()+self.name+PrintMenu()
pageText+="<div id='logframe'><iframe src='/logpage' width='100%' height='100%'>iFraming Not Supported?? No log for you.</iframe></div>" pageText+="<div id='logframe'><iframe src='/logpage' width='100%' height='100%'>iFraming Not Supported?? No log for you.</iframe></div>"
pageText+=PrintFooter() pageText+=PrintFooter()
return pageText return pageText
...@@ -80,7 +80,7 @@ class ConnectButton(object): ...@@ -80,7 +80,7 @@ class ConnectButton(object):
'tools.basic_auth.realm': 'My Print Server', 'tools.basic_auth.realm': 'My Print Server',
'tools.basic_auth.users': users, 'tools.basic_auth.users': users,
'tools.basic_auth.encrypt': clear_text} 'tools.basic_auth.encrypt': clear_text}
class DisconnectButton(object): class DisconnectButton(object):
def index(self): def index(self):
#handle connect push, then reload page #handle connect push, then reload page
...@@ -129,7 +129,7 @@ class MoveButton(object): ...@@ -129,7 +129,7 @@ class MoveButton(object):
def axis(self, *args): def axis(self, *args):
if not args: if not args:
raise cherrypy.HTTPError(400, "No Move Command Provided!") raise cherrypy.HTTPError(400, "No Move Command Provided!")
margs=list(args) margs = list(args)
axis = margs.pop(0) axis = margs.pop(0)
if(margs and axis == "x"): if(margs and axis == "x"):
distance = margs.pop(0) distance = margs.pop(0)
...@@ -149,12 +149,12 @@ class MoveButton(object): ...@@ -149,12 +149,12 @@ class MoveButton(object):
'tools.basic_auth.realm': 'My Print Server', 'tools.basic_auth.realm': 'My Print Server',
'tools.basic_auth.users': users, 'tools.basic_auth.users': users,
'tools.basic_auth.encrypt': clear_text} 'tools.basic_auth.encrypt': clear_text}
class CustomButton(object): class CustomButton(object):
def button(self, *args): def button(self, *args):
if not args: if not args:
raise cherrypy.HTTPError(400, "No Custom Command Provided!") raise cherrypy.HTTPError(400, "No Custom Command Provided!")
margs=list(args) margs = list(args)
command = margs.pop(0) command = margs.pop(0)
if(command): if(command):
gPronterPtr.onecmd(command) gPronterPtr.onecmd(command)
...@@ -164,12 +164,12 @@ class CustomButton(object): ...@@ -164,12 +164,12 @@ class CustomButton(object):
'tools.basic_auth.realm': 'My Print Server', 'tools.basic_auth.realm': 'My Print Server',
'tools.basic_auth.users': users, 'tools.basic_auth.users': users,
'tools.basic_auth.encrypt': clear_text} 'tools.basic_auth.encrypt': clear_text}
class HomeButton(object): class HomeButton(object):
def axis(self, *args): def axis(self, *args):
if not args: if not args:
raise cherrypy.HTTPError(400, "No Axis Provided!") raise cherrypy.HTTPError(400, "No Axis Provided!")
margs=list(args) margs = list(args)
taxis = margs.pop(0) taxis = margs.pop(0)
if(taxis == "x"): if(taxis == "x"):
gPronterPtr.onecmd('home X') gPronterPtr.onecmd('home X')
...@@ -183,41 +183,41 @@ class HomeButton(object): ...@@ -183,41 +183,41 @@ class HomeButton(object):
if(taxis == "all"): if(taxis == "all"):
gPronterPtr.onecmd('home') gPronterPtr.onecmd('home')
return ReloadPage("Home All") return ReloadPage("Home All")
axis.exposed = True axis.exposed = True
axis._cp_config = {'tools.basic_auth.on': True, axis._cp_config = {'tools.basic_auth.on': True,
'tools.basic_auth.realm': 'My Print Server', 'tools.basic_auth.realm': 'My Print Server',
'tools.basic_auth.users': users, 'tools.basic_auth.users': users,
'tools.basic_auth.encrypt': clear_text} 'tools.basic_auth.encrypt': clear_text}
class XMLstatus(object): class XMLstatus(object):
def index(self): def index(self):
#handle connect push, then reload page #handle connect push, then reload page
txt='<?xml version="1.0"?>\n<pronterface>\n' txt='<?xml version = "1.0"?>\n<pronterface>\n'
state="Offline" state = "Offline"
if gPronterPtr.statuscheck or gPronterPtr.p.online: if gPronterPtr.statuscheck or gPronterPtr.p.online:
state="Idle" state = "Idle"
if gPronterPtr.sdprinting: if gPronterPtr.sdprinting:
state="SDPrinting" state = "SDPrinting"
if gPronterPtr.p.printing: if gPronterPtr.p.printing:
state="Printing" state = "Printing"
if gPronterPtr.paused: if gPronterPtr.paused:
state="Paused" state = "Paused"
txt=txt+'<state>'+state+'</state>\n' txt = txt+'<state>'+state+'</state>\n'
txt=txt+'<file>'+str(gPronterPtr.filename)+'</file>\n' txt = txt+'<file>'+str(gPronterPtr.filename)+'</file>\n'
txt=txt+'<status>'+str(gPronterPtr.status.GetStatusText())+'</status>\n' txt = txt+'<status>'+str(gPronterPtr.status.GetStatusText())+'</status>\n'
try: try:
temp = str(float(filter(lambda x:x.startswith("T:"),gPronterPtr.tempreport.split())[0].split(":")[1])) temp = str(float(filter(lambda x:x.startswith("T:"), gPronterPtr.tempreport.split())[0].split(":")[1]))
txt=txt+'<hotend>'+temp+'</hotend>\n' txt = txt+'<hotend>'+temp+'</hotend>\n'
except: except:
txt=txt+'<hotend>NA</hotend>\n' txt = txt+'<hotend>NA</hotend>\n'
pass pass
try: try:
temp = str(float(filter(lambda x:x.startswith("B:"),gPronterPtr.tempreport.split())[0].split(":")[1])) temp = str(float(filter(lambda x:x.startswith("B:"), gPronterPtr.tempreport.split())[0].split(":")[1]))
txt=txt+'<bed>'+temp+'</bed>\n' txt = txt+'<bed>'+temp+'</bed>\n'
except: except:
txt=txt+'<bed>NA</bed>\n' txt = txt+'<bed>NA</bed>\n'
pass pass
if gPronterPtr.sdprinting: if gPronterPtr.sdprinting:
fractioncomplete = float(gPronterPtr.percentdone/100.0) fractioncomplete = float(gPronterPtr.percentdone/100.0)
...@@ -234,26 +234,26 @@ class XMLstatus(object): ...@@ -234,26 +234,26 @@ class XMLstatus(object):
index.exposed = True index.exposed = True
class WebInterface(object): class WebInterface(object):
def __init__(self, pface): def __init__(self, pface):
if (sys.version_info[1] > 6): if (sys.version_info[1] > 6):
# 'allow_no_value' wasn't added until 2.7 # 'allow_no_value' wasn't added until 2.7
config = ConfigParser.SafeConfigParser(allow_no_value=True) config = ConfigParser.SafeConfigParser(allow_no_value = True)
else: else:
config = ConfigParser.SafeConfigParser() config = ConfigParser.SafeConfigParser()
config.read(configfile(pface.web_auth_config or 'auth.config')) config.read(configfile(pface.web_auth_config or 'auth.config'))
users[config.get("user", "user")] = config.get("user", "pass") users[config.get("user", "user")] = config.get("user", "pass")
self.pface = pface self.pface = pface
global gPronterPtr global gPronterPtr
global gWeblog global gWeblog
self.name="<div id='title'>Pronterface Web-Interface</div>" self.name = "<div id='title'>Pronterface Web-Interface</div>"
gWeblog = "" gWeblog = ""
gPronterPtr = self.pface gPronterPtr = self.pface
settings = SettingsPage() settings = SettingsPage()
logpage = LogPage() logpage = LogPage()
console = ConsolePage() console = ConsolePage()
#actions #actions
connect = ConnectButton() connect = ConnectButton()
disconnect = DisconnectButton() disconnect = DisconnectButton()
...@@ -264,9 +264,9 @@ class WebInterface(object): ...@@ -264,9 +264,9 @@ class WebInterface(object):
home = HomeButton() home = HomeButton()
move = MoveButton() move = MoveButton()
custom =CustomButton() custom =CustomButton()
def index(self): def index(self):
pageText=PrintHeader()+self.name+PrintMenu() pageText = PrintHeader()+self.name+PrintMenu()
pageText+="<div id='content'>\n" pageText+="<div id='content'>\n"
pageText+="<div id='controls'>\n" pageText+="<div id='controls'>\n"
pageText+="<ul><li><a href='/connect'>Connect</a></li>\n" pageText+="<ul><li><a href='/connect'>Connect</a></li>\n"
...@@ -274,52 +274,52 @@ class WebInterface(object): ...@@ -274,52 +274,52 @@ class WebInterface(object):
pageText+="<li><a href='/reset'>Reset</a></li>\n" pageText+="<li><a href='/reset'>Reset</a></li>\n"
pageText+="<li><a href='/printbutton'>Print</a></li>\n" pageText+="<li><a href='/printbutton'>Print</a></li>\n"
pageText+="<li><a href='/pausebutton'>Pause</a></li>\n" pageText+="<li><a href='/pausebutton'>Pause</a></li>\n"
for i in gPronterPtr.cpbuttons: for i in gPronterPtr.cpbuttons:
pageText+="<li><a href='/custom/button/"+i[1]+"'>"+i[0]+"</a></li>\n" pageText+="<li><a href='/custom/button/"+i[1]+"'>"+i[0]+"</a></li>\n"
#for i in gPronterPtr.custombuttons: #for i in gPronterPtr.custombuttons:
# print(str(i)); # print(str(i));
pageText+="</ul>\n" pageText+="</ul>\n"
pageText+="</div>\n" pageText+="</div>\n"
pageText+="<div id='gui'>\n" pageText+="<div id='gui'>\n"
pageText+="<div id='control_xy'>" pageText+="<div id='control_xy'>"
pageText+="<img src='/images/control_xy.png' usemap='#xymap'/>" pageText+="<img src='/images/control_xy.png' usemap='#xymap'/>"
pageText+='<map name="xymap">' pageText+='<map name = "xymap">'
pageText+='<area shape="rect" coords="8,5,51,48" href="/home/axis/x" alt="X Home" title="X Home" />' pageText+='<area shape = "rect" coords = "8, 5, 51, 48" href = "/home/axis/x" alt = "X Home" title = "X Home" />'
pageText+='<area shape="rect" coords="195,6,236,46" href="/home/axis/y" alt="Y Home" title="Y Home" />' pageText+='<area shape = "rect" coords = "195, 6, 236, 46" href = "/home/axis/y" alt = "Y Home" title = "Y Home" />'
pageText+='<area shape="rect" coords="7,192,48,232" href="/home/axis/all" alt="All Home" title="All Home" />' pageText+='<area shape = "rect" coords = "7, 192, 48, 232" href = "/home/axis/all" alt = "All Home" title = "All Home" />'
pageText+='<area shape="rect" coords="194,192,235,232" href="/home/axis/z" alt="Z Home" title="Z Home" />' pageText+='<area shape = "rect" coords = "194, 192, 235, 232" href = "/home/axis/z" alt = "Z Home" title = "Z Home" />'
pageText+='<area shape="rect" coords="62,7,185,34" href="/move/axis/y/100" alt="Y 100" title="Y 100" />' pageText+='<area shape = "rect" coords = "62, 7, 185, 34" href = "/move/axis/y/100" alt = "Y 100" title = "Y 100" />'
pageText+='<area shape="rect" coords="68,34,175,61" href="/move/axis/y/10" alt="Y 10" title="Y 10" />' pageText+='<area shape = "rect" coords = "68, 34, 175, 61" href = "/move/axis/y/10" alt = "Y 10" title = "Y 10" />'
pageText+='<area shape="rect" coords="80,60,163,84" href="/move/axis/y/1" alt="Y 1" title="Y 1" />' pageText+='<area shape = "rect" coords = "80, 60, 163, 84" href = "/move/axis/y/1" alt = "Y 1" title = "Y 1" />'
pageText+='<area shape="rect" coords="106,83,138,107" href="/move/axis/y/.1" alt="Y .1" title="Y .1" />' pageText+='<area shape = "rect" coords = "106, 83, 138, 107" href = "/move/axis/y/.1" alt = "Y .1" title = "Y .1" />'
pageText+='<area shape="rect" coords="110,135,142,159" href="/move/axis/y/-.1" alt="Y -.1" title="Y -.1" />' pageText+='<area shape = "rect" coords = "110, 135, 142, 159" href = "/move/axis/y/-.1" alt = "Y -.1" title = "Y -.1" />'
pageText+='<area shape="rect" coords="81,157,169,181" href="/move/axis/y/-1" alt="Y -1" title="Y -1" />' pageText+='<area shape = "rect" coords = "81, 157, 169, 181" href = "/move/axis/y/-1" alt = "Y -1" title = "Y -1" />'
pageText+='<area shape="rect" coords="69,180,178,206" href="/move/axis/y/-10" alt="Y -10" title="Y -10" />' pageText+='<area shape = "rect" coords = "69, 180, 178, 206" href = "/move/axis/y/-10" alt = "Y -10" title = "Y -10" />'
pageText+='<area shape="rect" coords="60,205,186,231" href="/move/axis/y/-100" alt="Y -100" title="Y -100" />' pageText+='<area shape = "rect" coords = "60, 205, 186, 231" href = "/move/axis/y/-100" alt = "Y -100" title = "Y -100" />'
pageText+='<area shape="rect" coords="11,53,37,179" href="/move/axis/x/-100" alt="X -100" title="X -100" />' pageText+='<area shape = "rect" coords = "11, 53, 37, 179" href = "/move/axis/x/-100" alt = "X -100" title = "X -100" />'
pageText+='<area shape="rect" coords="210,59,236,185" href="/move/axis/x/100" alt="X 100" title="X 100" />' pageText+='<area shape = "rect" coords = "210, 59, 236, 185" href = "/move/axis/x/100" alt = "X 100" title = "X 100" />'
pageText+='<area shape="rect" coords="38,60,64,172" href="/move/axis/x/-10" alt="X -10" title="X -10" />' pageText+='<area shape = "rect" coords = "38, 60, 64, 172" href = "/move/axis/x/-10" alt = "X -10" title = "X -10" />'
pageText+='<area shape="rect" coords="185,66,211,178" href="/move/axis/x/10" alt="X 10" title="X 10" />' pageText+='<area shape = "rect" coords = "185, 66, 211, 178" href = "/move/axis/x/10" alt = "X 10" title = "X 10" />'
pageText+='<area shape="rect" coords="62,84,83,157" href="/move/axis/x/-1" alt="X -1" title="X -1" />' pageText+='<area shape = "rect" coords = "62, 84, 83, 157" href = "/move/axis/x/-1" alt = "X -1" title = "X -1" />'
pageText+='<area shape="rect" coords="163,87,187,160" href="/move/axis/x/1" alt="X 1" title="X 1" />' pageText+='<area shape = "rect" coords = "163, 87, 187, 160" href = "/move/axis/x/1" alt = "X 1" title = "X 1" />'
pageText+='<area shape="rect" coords="82,104,110,139" href="/move/axis/x/-.1" alt="X -.1" title="X -.1" />' pageText+='<area shape = "rect" coords = "82, 104, 110, 139" href = "/move/axis/x/-.1" alt = "X -.1" title = "X -.1" />'
pageText+='<area shape="rect" coords="137,105,165,140" href="/move/axis/x/.1" alt="X .1" title="X .1" />' pageText+='<area shape = "rect" coords = "137, 105, 165, 140" href = "/move/axis/x/.1" alt = "X .1" title = "X .1" />'
pageText+="</map>" pageText+="</map>"
pageText+="</div>\n" #endxy pageText+="</div>\n" #endxy
pageText+="<div id='control_z'>" pageText+="<div id='control_z'>"
pageText+="<img src='/images/control_z.png' usemap='#zmap'/>" pageText+="<img src='/images/control_z.png' usemap='#zmap'/>"
pageText+='<map name="zmap">' pageText+='<map name = "zmap">'
pageText+='<area shape="rect" coords="4,35,54,64" href="/move/axis/z/10" alt="Z 10" title="Z 10" />' pageText+='<area shape = "rect" coords = "4, 35, 54, 64" href = "/move/axis/z/10" alt = "Z 10" title = "Z 10" />'
pageText+='<area shape="rect" coords="4,60,54,89" href="/move/axis/z/1" alt="Z 1" title="Z 1" />' pageText+='<area shape = "rect" coords = "4, 60, 54, 89" href = "/move/axis/z/1" alt = "Z 1" title = "Z 1" />'
pageText+='<area shape="rect" coords="4,87,54,116" href="/move/axis/z/.1" alt="Z .1" title="Z .1" />' pageText+='<area shape = "rect" coords = "4, 87, 54, 116" href = "/move/axis/z/.1" alt = "Z .1" title = "Z .1" />'
pageText+='<area shape="rect" coords="4,121,54,150" href="/move/axis/z/-.1" alt="Z -.1" title="Z -.1" />' pageText+='<area shape = "rect" coords = "4, 121, 54, 150" href = "/move/axis/z/-.1" alt = "Z -.1" title = "Z -.1" />'
pageText+='<area shape="rect" coords="4,147,54,176" href="/move/axis/z/-1" alt="Z -1" title="Z -1" />' pageText+='<area shape = "rect" coords = "4, 147, 54, 176" href = "/move/axis/z/-1" alt = "Z -1" title = "Z -1" />'
pageText+='<area shape="rect" coords="4,173,54,202" href="/move/axis/z/-10" alt="Z -10" title="Z -10" />' pageText+='<area shape = "rect" coords = "4, 173, 54, 202" href = "/move/axis/z/-10" alt = "Z -10" title = "Z -10" />'
pageText+="</map>" pageText+="</map>"
#TODO Map Z Moves #TODO Map Z Moves
pageText+="</div>\n" #endz pageText+="</div>\n" #endz
...@@ -336,18 +336,18 @@ class WebInterface(object): ...@@ -336,18 +336,18 @@ class WebInterface(object):
# pageText+="<ul><li><b>Bed Temp:</b></li><li><a href='/off'>OFF</a></li><li><a href='/185'>185 (PLA)</a></li><li><a href='/240'>240 (ABS)</a></li></ul>" # pageText+="<ul><li><b>Bed Temp:</b></li><li><a href='/off'>OFF</a></li><li><a href='/185'>185 (PLA)</a></li><li><a href='/240'>240 (ABS)</a></li></ul>"
# pageText+="</div>" # pageText+="</div>"
# pageText+="</div>" # pageText+="</div>"
pageText=pageText+"<div id='file'>File Loaded: <i>"+str(gPronterPtr.filename)+"</i></div>" pageText = pageText+"<div id='file'>File Loaded: <i>"+str(gPronterPtr.filename)+"</i></div>"
pageText+="<div id='logframe'><iframe src='/logpage' width='100%' height='100%'>iFraming Not Supported?? No log for you.</iframe></div>" pageText+="<div id='logframe'><iframe src='/logpage' width='100%' height='100%'>iFraming Not Supported?? No log for you.</iframe></div>"
pageText+=PrintFooter() pageText+=PrintFooter()
return pageText return pageText
def AddLog(self, log): def AddLog(self, log):
global gWeblog global gWeblog
gWeblog=gWeblog+"</br>"+log gWeblog = gWeblog+"</br>"+log
def AppendLog(self, log): def AppendLog(self, log):
global gWeblog global gWeblog
gWeblog=re.sub("\n", "</br>", gWeblog)+log gWeblog = re.sub("\n", "</br>", gWeblog)+log
index.exposed = True index.exposed = True
class WebInterfaceStub(object): class WebInterfaceStub(object):
...@@ -357,7 +357,7 @@ class WebInterfaceStub(object): ...@@ -357,7 +357,7 @@ class WebInterfaceStub(object):
def KillWebInterfaceThread(): def KillWebInterfaceThread():
cherrypy.engine.exit() cherrypy.engine.exit()
def StartWebInterfaceThread(webInterface): def StartWebInterfaceThread(webInterface):
current_dir = os.path.dirname(os.path.abspath(__file__)) current_dir = os.path.dirname(os.path.abspath(__file__))
cherrypy.config.update({'engine.autoreload_on':False}) cherrypy.config.update({'engine.autoreload_on':False})
...@@ -372,7 +372,7 @@ def StartWebInterfaceThread(webInterface): ...@@ -372,7 +372,7 @@ def StartWebInterfaceThread(webInterface):
'tools.staticfile.filename': imagefile('control_z.png'), 'tools.staticfile.filename': imagefile('control_z.png'),
}} }}
cherrypy.config.update(configfile(webInterface.pface.web_config or "http.config")) cherrypy.config.update(configfile(webInterface.pface.web_config or "http.config"))
cherrypy.quickstart(webInterface, '/', config=conf) cherrypy.quickstart(webInterface, '/', config = conf)
if __name__ == '__main__': if __name__ == '__main__':
cherrypy.config.update(configfile("http.config")) cherrypy.config.update(configfile("http.config"))
......
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import wx, os, math import wx, os, math
from bufferedcanvas import * from bufferedcanvas import *
from printrun_utils import * from printrun_utils import *
def sign(n): def sign(n):
if n < 0: return -1 if n < 0: return -1
...@@ -41,9 +41,9 @@ class XYButtons(BufferedCanvas): ...@@ -41,9 +41,9 @@ class XYButtons(BufferedCanvas):
center = (124, 121) center = (124, 121)
spacer = 7 spacer = 7
def __init__(self, parent, moveCallback=None, cornerCallback=None, spacebarCallback=None, bgcolor="#FFFFFF", ID=-1): def __init__(self, parent, moveCallback = None, cornerCallback = None, spacebarCallback = None, bgcolor = "#FFFFFF", ID=-1):
self.bg_bmp = wx.Image(imagefile("control_xy.png"),wx.BITMAP_TYPE_PNG).ConvertToBitmap() self.bg_bmp = wx.Image(imagefile("control_xy.png"), wx.BITMAP_TYPE_PNG).ConvertToBitmap()
self.keypad_bmp = wx.Image(imagefile("arrow_keys.png"),wx.BITMAP_TYPE_PNG).ConvertToBitmap() self.keypad_bmp = wx.Image(imagefile("arrow_keys.png"), wx.BITMAP_TYPE_PNG).ConvertToBitmap()
self.keypad_idx = -1 self.keypad_idx = -1
self.quadrant = None self.quadrant = None
self.concentric = None self.concentric = None
...@@ -56,10 +56,10 @@ class XYButtons(BufferedCanvas): ...@@ -56,10 +56,10 @@ class XYButtons(BufferedCanvas):
self.lastMove = None self.lastMove = None
self.lastCorner = None self.lastCorner = None
self.bgcolor = wx.Colour() self.bgcolor = wx.Colour()
self.bgcolor.SetFromName(bgcolor) self.bgcolor.SetFromName(bgcolor)
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128) self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
BufferedCanvas.__init__(self, parent, ID) BufferedCanvas.__init__(self, parent, ID)
self.SetSize(self.bg_bmp.GetSize()) self.SetSize(self.bg_bmp.GetSize())
...@@ -70,11 +70,11 @@ class XYButtons(BufferedCanvas): ...@@ -70,11 +70,11 @@ class XYButtons(BufferedCanvas):
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow) self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
self.Bind(wx.EVT_KEY_UP, self.OnKey) self.Bind(wx.EVT_KEY_UP, self.OnKey)
wx.GetTopLevelParent(self).Bind(wx.EVT_CHAR_HOOK, self.OnTopLevelKey) wx.GetTopLevelParent(self).Bind(wx.EVT_CHAR_HOOK, self.OnTopLevelKey)
def disable(self): def disable(self):
self.enabled = False self.enabled = False
self.update() self.update()
def enable(self): def enable(self):
self.enabled = True self.enabled = True
self.update() self.update()
...@@ -84,7 +84,7 @@ class XYButtons(BufferedCanvas): ...@@ -84,7 +84,7 @@ class XYButtons(BufferedCanvas):
self.moveCallback(*self.lastMove) self.moveCallback(*self.lastMove)
if self.lastCorner: if self.lastCorner:
self.cornerCallback(self.lastCorner) self.cornerCallback(self.lastCorner)
def clearRepeat(self): def clearRepeat(self):
self.lastMove = None self.lastMove = None
self.lastCorner = None self.lastCorner = None
...@@ -95,7 +95,7 @@ class XYButtons(BufferedCanvas): ...@@ -95,7 +95,7 @@ class XYButtons(BufferedCanvas):
pxlen = x1 - pos.x pxlen = x1 - pos.x
pylen = y1 - pos.y pylen = y1 - pos.y
return abs(xlen*pylen-ylen*pxlen)/math.sqrt(xlen**2+ylen**2) return abs(xlen*pylen-ylen*pxlen)/math.sqrt(xlen**2+ylen**2)
def distanceToPoint(self, x1, y1, x2, y2): def distanceToPoint(self, x1, y1, x2, y2):
return math.sqrt((x1-x2)**2 + (y1-y2)**2) return math.sqrt((x1-x2)**2 + (y1-y2)**2)
...@@ -103,17 +103,17 @@ class XYButtons(BufferedCanvas): ...@@ -103,17 +103,17 @@ class XYButtons(BufferedCanvas):
idx = self.keypad_idx + 1 idx = self.keypad_idx + 1
if idx > 2: idx = 0 if idx > 2: idx = 0
return idx return idx
def setKeypadIndex(self, idx): def setKeypadIndex(self, idx):
self.keypad_idx = idx self.keypad_idx = idx
self.update() self.update()
def getMovement(self): def getMovement(self):
xdir = [1, 0, -1, 0][self.quadrant] xdir = [1, 0, -1, 0][self.quadrant]
ydir = [0, 1, 0, -1][self.quadrant] ydir = [0, 1, 0, -1][self.quadrant]
magnitude = math.pow(10, self.concentric-1) magnitude = math.pow(10, self.concentric-1)
return (magnitude * xdir, magnitude * ydir) return (magnitude * xdir, magnitude * ydir)
def lookupConcentric(self, radius): def lookupConcentric(self, radius):
idx = 0 idx = 0
for r in XYButtons.concentric_circle_radii[1:]: for r in XYButtons.concentric_circle_radii[1:]:
...@@ -134,27 +134,27 @@ class XYButtons(BufferedCanvas): ...@@ -134,27 +134,27 @@ class XYButtons(BufferedCanvas):
quadrant = 1 # Up quadrant = 1 # Up
else: else:
quadrant = 2 # Left quadrant = 2 # Left
idx = self.lookupConcentric(radius) idx = self.lookupConcentric(radius)
return (quadrant, idx) return (quadrant, idx)
def mouseOverKeypad(self, mpos): def mouseOverKeypad(self, mpos):
for idx, kpos in XYButtons.keypad_positions.items(): for idx, kpos in XYButtons.keypad_positions.items():
radius = self.distanceToPoint(mpos[0], mpos[1], kpos[0], kpos[1]) radius = self.distanceToPoint(mpos[0], mpos[1], kpos[0], kpos[1])
if radius < 9: if radius < 9:
return idx return idx
return None return None
def drawPartialPie(self, gc, center, r1, r2, angle1, angle2): def drawPartialPie(self, gc, center, r1, r2, angle1, angle2):
p1 = wx.Point(center.x + r1*math.cos(angle1), center.y + r1*math.sin(angle1)) p1 = wx.Point(center.x + r1*math.cos(angle1), center.y + r1*math.sin(angle1))
path = gc.CreatePath() path = gc.CreatePath()
path.MoveToPoint(p1.x, p1.y) path.MoveToPoint(p1.x, p1.y)
path.AddArc(center.x, center.y, r1, angle1, angle2, True) path.AddArc(center.x, center.y, r1, angle1, angle2, True)
path.AddArc(center.x, center.y, r2, angle2, angle1, False) path.AddArc(center.x, center.y, r2, angle2, angle1, False)
path.AddLineToPoint(p1.x, p1.y) path.AddLineToPoint(p1.x, p1.y)
gc.DrawPath(path) gc.DrawPath(path)
def highlightQuadrant(self, gc, quadrant, concentric): def highlightQuadrant(self, gc, quadrant, concentric):
assert(quadrant >= 0 and quadrant <= 3) assert(quadrant >= 0 and quadrant <= 3)
assert(concentric >= 0 and concentric <= 3) assert(concentric >= 0 and concentric <= 3)
...@@ -175,13 +175,13 @@ class XYButtons(BufferedCanvas): ...@@ -175,13 +175,13 @@ class XYButtons(BufferedCanvas):
elif quadrant == 3: elif quadrant == 3:
a1, a2 = (math.pi*0.25, math.pi*0.75) a1, a2 = (math.pi*0.25, math.pi*0.75)
center.y += inner_ring_radius center.y += inner_ring_radius
r1 = XYButtons.concentric_circle_radii[concentric] r1 = XYButtons.concentric_circle_radii[concentric]
r2 = XYButtons.concentric_circle_radii[concentric+1] r2 = XYButtons.concentric_circle_radii[concentric+1]
self.drawPartialPie(gc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge) self.drawPartialPie(gc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge)
def drawCorner(self, gc, x, y, angle=0.0): def drawCorner(self, gc, x, y, angle = 0.0):
w, h = XYButtons.corner_size w, h = XYButtons.corner_size
gc.PushState() gc.PushState()
...@@ -197,11 +197,11 @@ class XYButtons(BufferedCanvas): ...@@ -197,11 +197,11 @@ class XYButtons(BufferedCanvas):
gc.DrawPath(path) gc.DrawPath(path)
gc.PopState() gc.PopState()
def highlightCorner(self, gc, corner=0): def highlightCorner(self, gc, corner = 0):
w, h = XYButtons.corner_size w, h = XYButtons.corner_size
cx, cy = XYButtons.center cx, cy = XYButtons.center
ww, wh = self.GetSizeTuple() ww, wh = self.GetSizeTuple()
inset = 10 inset = 10
if corner == 0: if corner == 0:
x, y = (cx - ww/2 + inset, cy - wh/2 + inset) x, y = (cx - ww/2 + inset, cy - wh/2 + inset)
...@@ -215,10 +215,10 @@ class XYButtons(BufferedCanvas): ...@@ -215,10 +215,10 @@ class XYButtons(BufferedCanvas):
elif corner == 3: elif corner == 3:
x, y = (cx - ww/2 + inset, cy + wh/2 - inset) x, y = (cx - ww/2 + inset, cy + wh/2 - inset)
self.drawCorner(gc, x+w/2, y-h/2, math.pi*3/2) self.drawCorner(gc, x+w/2, y-h/2, math.pi*3/2)
def draw(self, dc, w, h): def draw(self, dc, w, h):
dc.SetBackground(wx.Brush(self.bgcolor)) dc.SetBackground(wx.Brush(self.bgcolor))
dc.Clear() dc.Clear()
gc = wx.GraphicsContext.Create(dc) gc = wx.GraphicsContext.Create(dc)
...@@ -226,11 +226,11 @@ class XYButtons(BufferedCanvas): ...@@ -226,11 +226,11 @@ class XYButtons(BufferedCanvas):
if self.bg_bmp: if self.bg_bmp:
w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight()) w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight())
gc.DrawBitmap(self.bg_bmp, 0, 0, w, h) gc.DrawBitmap(self.bg_bmp, 0, 0, w, h)
if self.enabled: if self.enabled:
# Brush and pen for grey overlay when mouse hovers over # Brush and pen for grey overlay when mouse hovers over
gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4)) gc.SetPen(wx.Pen(wx.Colour(100, 100, 100, 172), 4))
gc.SetBrush(wx.Brush(wx.Colour(0,0,0,128))) gc.SetBrush(wx.Brush(wx.Colour(0, 0, 0, 128)))
if self.concentric != None: if self.concentric != None:
if self.concentric < len(XYButtons.concentric_circle_radii): if self.concentric < len(XYButtons.concentric_circle_radii):
...@@ -238,16 +238,16 @@ class XYButtons(BufferedCanvas): ...@@ -238,16 +238,16 @@ class XYButtons(BufferedCanvas):
self.highlightQuadrant(gc, self.quadrant, self.concentric) self.highlightQuadrant(gc, self.quadrant, self.concentric)
elif self.corner != None: elif self.corner != None:
self.highlightCorner(gc, self.corner) self.highlightCorner(gc, self.corner)
if self.keypad_idx >= 0: if self.keypad_idx >= 0:
padw, padh = (self.keypad_bmp.GetWidth(), self.keypad_bmp.GetHeight()) padw, padh = (self.keypad_bmp.GetWidth(), self.keypad_bmp.GetHeight())
pos = XYButtons.keypad_positions[self.keypad_idx] pos = XYButtons.keypad_positions[self.keypad_idx]
pos = (pos[0] - padw/2 - 3, pos[1] - padh/2 - 3) pos = (pos[0] - padw/2 - 3, pos[1] - padh/2 - 3)
gc.DrawBitmap(self.keypad_bmp, pos[0], pos[1], padw, padh) gc.DrawBitmap(self.keypad_bmp, pos[0], pos[1], padw, padh)
# Draw label overlays # Draw label overlays
gc.SetPen(wx.Pen(wx.Colour(255,255,255,128), 1)) gc.SetPen(wx.Pen(wx.Colour(255, 255, 255, 128), 1))
gc.SetBrush(wx.Brush(wx.Colour(255,255,255,128+64))) gc.SetBrush(wx.Brush(wx.Colour(255, 255, 255, 128+64)))
for idx, kpos in XYButtons.label_overlay_positions.items(): for idx, kpos in XYButtons.label_overlay_positions.items():
if idx != self.concentric: if idx != self.concentric:
r = kpos[2] r = kpos[2]
...@@ -256,7 +256,7 @@ class XYButtons(BufferedCanvas): ...@@ -256,7 +256,7 @@ class XYButtons(BufferedCanvas):
gc.SetPen(wx.Pen(self.bgcolor, 0)) gc.SetPen(wx.Pen(self.bgcolor, 0))
gc.SetBrush(wx.Brush(self.bgcolormask)) gc.SetBrush(wx.Brush(self.bgcolormask))
gc.DrawRectangle(0, 0, w, h) gc.DrawRectangle(0, 0, w, h)
# Used to check exact position of keypad dots, should we ever resize the bg image # Used to check exact position of keypad dots, should we ever resize the bg image
# for idx, kpos in XYButtons.label_overlay_positions.items(): # for idx, kpos in XYButtons.label_overlay_positions.items():
...@@ -289,7 +289,7 @@ class XYButtons(BufferedCanvas): ...@@ -289,7 +289,7 @@ class XYButtons(BufferedCanvas):
else: else:
evt.Skip() evt.Skip()
return return
if self.moveCallback: if self.moveCallback:
self.concentric = self.keypad_idx self.concentric = self.keypad_idx
x, y = self.getMovement() x, y = self.getMovement()
...@@ -301,7 +301,7 @@ class XYButtons(BufferedCanvas): ...@@ -301,7 +301,7 @@ class XYButtons(BufferedCanvas):
def OnMotion(self, event): def OnMotion(self, event):
if not self.enabled: if not self.enabled:
return return
oldcorner = self.corner oldcorner = self.corner
oldq, oldc = self.quadrant, self.concentric oldq, oldc = self.quadrant, self.concentric
...@@ -318,7 +318,7 @@ class XYButtons(BufferedCanvas): ...@@ -318,7 +318,7 @@ class XYButtons(BufferedCanvas):
# If mouse hovers in space between quadrants, don't commit to a quadrant # If mouse hovers in space between quadrants, don't commit to a quadrant
if riseDist <= XYButtons.spacer or fallDist <= XYButtons.spacer: if riseDist <= XYButtons.spacer or fallDist <= XYButtons.spacer:
self.quadrant = None self.quadrant = None
cx, cy = XYButtons.center cx, cy = XYButtons.center
if mpos.x < cx and mpos.y < cy: if mpos.x < cx and mpos.y < cy:
self.corner = 0 self.corner = 0
...@@ -335,7 +335,7 @@ class XYButtons(BufferedCanvas): ...@@ -335,7 +335,7 @@ class XYButtons(BufferedCanvas):
def OnLeftDown(self, event): def OnLeftDown(self, event):
if not self.enabled: if not self.enabled:
return return
# Take focus when clicked so that arrow keys can control movement # Take focus when clicked so that arrow keys can control movement
self.SetFocus() self.SetFocus()
...@@ -362,7 +362,7 @@ class XYButtons(BufferedCanvas): ...@@ -362,7 +362,7 @@ class XYButtons(BufferedCanvas):
self.setKeypadIndex(-1) self.setKeypadIndex(-1)
else: else:
self.setKeypadIndex(idx) self.setKeypadIndex(idx)
def OnLeaveWindow(self, evt): def OnLeaveWindow(self, evt):
self.quadrant = None self.quadrant = None
self.concentric = None self.concentric = None
......
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import wx, os, math import wx, os, math
from bufferedcanvas import * from bufferedcanvas import *
from printrun_utils import * from printrun_utils import *
def sign(n): def sign(n):
if n < 0: return -1 if n < 0: return -1
...@@ -32,8 +32,8 @@ class ZButtons(BufferedCanvas): ...@@ -32,8 +32,8 @@ class ZButtons(BufferedCanvas):
3: None 3: None
} }
def __init__(self, parent, moveCallback=None, bgcolor="#FFFFFF", ID=-1): def __init__(self, parent, moveCallback = None, bgcolor = "#FFFFFF", ID=-1):
self.bg_bmp = wx.Image(imagefile("control_z.png"),wx.BITMAP_TYPE_PNG).ConvertToBitmap() self.bg_bmp = wx.Image(imagefile("control_z.png"), wx.BITMAP_TYPE_PNG).ConvertToBitmap()
self.range = None self.range = None
self.direction = None self.direction = None
self.orderOfMagnitudeIdx = 0 # 0 means '1', 1 means '10', 2 means '100', etc. self.orderOfMagnitudeIdx = 0 # 0 means '1', 1 means '10', 2 means '100', etc.
...@@ -42,9 +42,9 @@ class ZButtons(BufferedCanvas): ...@@ -42,9 +42,9 @@ class ZButtons(BufferedCanvas):
# Remember the last clicked value, so we can repeat when spacebar pressed # Remember the last clicked value, so we can repeat when spacebar pressed
self.lastValue = None self.lastValue = None
self.bgcolor = wx.Colour() self.bgcolor = wx.Colour()
self.bgcolor.SetFromName(bgcolor) self.bgcolor.SetFromName(bgcolor)
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128) self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
BufferedCanvas.__init__(self, parent, ID) BufferedCanvas.__init__(self, parent, ID)
...@@ -59,7 +59,7 @@ class ZButtons(BufferedCanvas): ...@@ -59,7 +59,7 @@ class ZButtons(BufferedCanvas):
def disable(self): def disable(self):
self.enabled = False self.enabled = False
self.update() self.update()
def enable(self): def enable(self):
self.enabled = True self.enabled = True
self.update() self.update()
...@@ -78,7 +78,7 @@ class ZButtons(BufferedCanvas): ...@@ -78,7 +78,7 @@ class ZButtons(BufferedCanvas):
return idx return idx
idx += 1 idx += 1
return None return None
def highlight(self, gc, rng, dir): def highlight(self, gc, rng, dir):
assert(rng >= -1 and rng <= 3) assert(rng >= -1 and rng <= 3)
assert(dir >= -1 and dir <= 1) assert(dir >= -1 and dir <= 1)
...@@ -93,13 +93,13 @@ class ZButtons(BufferedCanvas): ...@@ -93,13 +93,13 @@ class ZButtons(BufferedCanvas):
gc.DrawRoundedRectangle(x, y, w, h, 4) gc.DrawRoundedRectangle(x, y, w, h, 4)
# gc.DrawRectangle(x, y, w, h) # gc.DrawRectangle(x, y, w, h)
# self.drawPartialPie(dc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge) # self.drawPartialPie(dc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge)
def getRangeDir(self, pos): def getRangeDir(self, pos):
ydelta = ZButtons.center[1] - pos[1] ydelta = ZButtons.center[1] - pos[1]
return (self.lookupRange(abs(ydelta)), sign(ydelta)) return (self.lookupRange(abs(ydelta)), sign(ydelta))
def draw(self, dc, w, h): def draw(self, dc, w, h):
dc.SetBackground(wx.Brush(self.bgcolor)) dc.SetBackground(wx.Brush(self.bgcolor))
dc.Clear() dc.Clear()
gc = wx.GraphicsContext.Create(dc) gc = wx.GraphicsContext.Create(dc)
if self.bg_bmp: if self.bg_bmp:
...@@ -108,16 +108,16 @@ class ZButtons(BufferedCanvas): ...@@ -108,16 +108,16 @@ class ZButtons(BufferedCanvas):
if self.enabled: if self.enabled:
# Draw label overlays # Draw label overlays
gc.SetPen(wx.Pen(wx.Colour(255,255,255,128), 1)) gc.SetPen(wx.Pen(wx.Colour(255, 255, 255, 128), 1))
gc.SetBrush(wx.Brush(wx.Colour(255,255,255,128+64))) gc.SetBrush(wx.Brush(wx.Colour(255, 255, 255, 128+64)))
for idx, kpos in ZButtons.label_overlay_positions.items(): for idx, kpos in ZButtons.label_overlay_positions.items():
if kpos and idx != self.range: if kpos and idx != self.range:
r = kpos[2] r = kpos[2]
gc.DrawEllipse(ZButtons.center[0]-kpos[0]-r, ZButtons.center[1]-kpos[1]-r, r*2, r*2) gc.DrawEllipse(ZButtons.center[0]-kpos[0]-r, ZButtons.center[1]-kpos[1]-r, r*2, r*2)
# Top 'layer' is the mouse-over highlights # Top 'layer' is the mouse-over highlights
gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4)) gc.SetPen(wx.Pen(wx.Colour(100, 100, 100, 172), 4))
gc.SetBrush(wx.Brush(wx.Colour(0,0,0,128))) gc.SetBrush(wx.Brush(wx.Colour(0, 0, 0, 128)))
if self.range != None and self.direction != None: if self.range != None and self.direction != None:
self.highlight(gc, self.range, self.direction) self.highlight(gc, self.range, self.direction)
else: else:
...@@ -132,7 +132,7 @@ class ZButtons(BufferedCanvas): ...@@ -132,7 +132,7 @@ class ZButtons(BufferedCanvas):
def OnMotion(self, event): def OnMotion(self, event):
if not self.enabled: if not self.enabled:
return return
oldr, oldd = self.range, self.direction oldr, oldd = self.range, self.direction
mpos = event.GetPosition() mpos = event.GetPosition()
......
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import wx,math import wx, math
from stltool import * from stltool import *
a=wx.App() a = wx.App()
def genscape(data=[[0,1,0,0],[1,0,2,0],[1,0,0,0],[0,1,0,1]],pscale=1.0,bheight=1.0,zscale=1.0): def genscape(data = [[0, 1, 0, 0],[1, 0, 2, 0],[1, 0, 0, 0],[0, 1, 0, 1]], pscale = 1.0, bheight = 1.0, zscale = 1.0):
o=stl(None) o = stl(None)
datal=len(data) datal = len(data)
datah=len(data[0]) datah = len(data[0])
#create bottom: #create bottom:
bmidpoint=(pscale*(datal-1)/2.0,pscale*(datah-1)/2.0) bmidpoint = (pscale*(datal-1)/2.0, pscale*(datah-1)/2.0)
#print range(datal),bmidpoint #print range(datal), bmidpoint
for i in zip(range(datal+1)[:-1],range(datal+1)[1:])[:-1]: for i in zip(range(datal+1)[:-1], range(datal+1)[1:])[:-1]:
#print (pscale*i[0],pscale*i[1]) #print (pscale*i[0], pscale*i[1])
o.facets+=[[[0,0,-1],[[0.0,pscale*i[0],0.0],[0.0,pscale*i[1],0.0],[bmidpoint[0],bmidpoint[1],0.0]]]] o.facets+=[[[0, 0,-1],[[0.0, pscale*i[0], 0.0],[0.0, pscale*i[1], 0.0],[bmidpoint[0], bmidpoint[1], 0.0]]]]
o.facets+=[[[0,0,-1],[[2.0*bmidpoint[1],pscale*i[1],0.0],[2.0*bmidpoint[1],pscale*i[0],0.0],[bmidpoint[0],bmidpoint[1],0.0]]]] o.facets+=[[[0, 0,-1],[[2.0*bmidpoint[1], pscale*i[1], 0.0],[2.0*bmidpoint[1], pscale*i[0], 0.0],[bmidpoint[0], bmidpoint[1], 0.0]]]]
o.facets+=[genfacet([[0.0,pscale*i[0],data[i[0]][0]*zscale+bheight],[0.0,pscale*i[1],data[i[1]][0]*zscale+bheight],[0.0,pscale*i[1],0.0]])] o.facets+=[genfacet([[0.0, pscale*i[0], data[i[0]][0]*zscale+bheight],[0.0, pscale*i[1], data[i[1]][0]*zscale+bheight],[0.0, pscale*i[1], 0.0]])]
o.facets+=[genfacet([[2.0*bmidpoint[1],pscale*i[1],data[i[1]][datah-1]*zscale+bheight],[2.0*bmidpoint[1],pscale*i[0],data[i[0]][datah-1]*zscale+bheight],[2.0*bmidpoint[1],pscale*i[1],0.0]])] o.facets+=[genfacet([[2.0*bmidpoint[1], pscale*i[1], data[i[1]][datah-1]*zscale+bheight],[2.0*bmidpoint[1], pscale*i[0], data[i[0]][datah-1]*zscale+bheight],[2.0*bmidpoint[1], pscale*i[1], 0.0]])]
o.facets+=[genfacet([[0.0,pscale*i[0],data[i[0]][0]*zscale+bheight],[0.0,pscale*i[1],0.0],[0.0,pscale*i[0],0.0]])] o.facets+=[genfacet([[0.0, pscale*i[0], data[i[0]][0]*zscale+bheight],[0.0, pscale*i[1], 0.0],[0.0, pscale*i[0], 0.0]])]
o.facets+=[genfacet([[2.0*bmidpoint[1],pscale*i[1],0.0],[2.0*bmidpoint[1],pscale*i[0],data[i[0]][datah-1]*zscale+bheight],[2.0*bmidpoint[1],pscale*i[0],0.0]])] o.facets+=[genfacet([[2.0*bmidpoint[1], pscale*i[1], 0.0],[2.0*bmidpoint[1], pscale*i[0], data[i[0]][datah-1]*zscale+bheight],[2.0*bmidpoint[1], pscale*i[0], 0.0]])]
#print o.facets[-1] #print o.facets[-1]
pass pass
#print o.facets[-4:] #print o.facets[-4:]
for i in zip(range(datah+1)[:-1],range(datah+1)[1:])[:-1]: for i in zip(range(datah+1)[:-1], range(datah+1)[1:])[:-1]:
#print (pscale*i[0],pscale*i[1]) #print (pscale*i[0], pscale*i[1])
o.facets+=[[[0,0,-1],[[pscale*i[1],0.0,0.0],[pscale*i[0],0.0,0.0],[bmidpoint[0],bmidpoint[1],0.0]]]] o.facets+=[[[0, 0,-1],[[pscale*i[1], 0.0, 0.0],[pscale*i[0], 0.0, 0.0],[bmidpoint[0], bmidpoint[1], 0.0]]]]
o.facets+=[[[0,0,-1],[[pscale*i[0],2.0*bmidpoint[0],0.0],[pscale*i[1],2.0*bmidpoint[0],0.0],[bmidpoint[0],bmidpoint[1],0.0]]]] o.facets+=[[[0, 0,-1],[[pscale*i[0], 2.0*bmidpoint[0], 0.0],[pscale*i[1], 2.0*bmidpoint[0], 0.0],[bmidpoint[0], bmidpoint[1], 0.0]]]]
o.facets+=[genfacet([[pscale*i[1],0.0,data[0][i[1]]*zscale+bheight],[pscale*i[0],0.0,data[0][i[0]]*zscale+bheight],[pscale*i[1],0.0,0.0]])] o.facets+=[genfacet([[pscale*i[1], 0.0, data[0][i[1]]*zscale+bheight],[pscale*i[0], 0.0, data[0][i[0]]*zscale+bheight],[pscale*i[1], 0.0, 0.0]])]
#break #break
o.facets+=[genfacet([[pscale*i[0],2.0*bmidpoint[0],data[datal-1][i[0]]*zscale+bheight],[pscale*i[1],2.0*bmidpoint[0],data[datal-1][i[1]]*zscale+bheight],[pscale*i[1],2.0*bmidpoint[0],0.0]])] o.facets+=[genfacet([[pscale*i[0], 2.0*bmidpoint[0], data[datal-1][i[0]]*zscale+bheight],[pscale*i[1], 2.0*bmidpoint[0], data[datal-1][i[1]]*zscale+bheight],[pscale*i[1], 2.0*bmidpoint[0], 0.0]])]
o.facets+=[genfacet([[pscale*i[1],0.0,0.0],[pscale*i[0],0.0,data[0][i[0]]*zscale+bheight],[pscale*i[0],0.0,0.0]])] o.facets+=[genfacet([[pscale*i[1], 0.0, 0.0],[pscale*i[0], 0.0, data[0][i[0]]*zscale+bheight],[pscale*i[0], 0.0, 0.0]])]
o.facets+=[genfacet([[pscale*i[0],2.0*bmidpoint[0],data[datal-1][i[0]]*zscale+bheight],[pscale*i[1],2.0*bmidpoint[0],0.0],[pscale*i[0],2.0*bmidpoint[0],0.0]])] o.facets+=[genfacet([[pscale*i[0], 2.0*bmidpoint[0], data[datal-1][i[0]]*zscale+bheight],[pscale*i[1], 2.0*bmidpoint[0], 0.0],[pscale*i[0], 2.0*bmidpoint[0], 0.0]])]
pass pass
for i in xrange(datah-1): for i in xrange(datah-1):
for j in xrange(datal-1): for j in xrange(datal-1):
o.facets+=[genfacet([[pscale*i,pscale*j,data[j][i]*zscale+bheight],[pscale*(i+1),pscale*(j),data[j][i+1]*zscale+bheight],[pscale*(i+1),pscale*(j+1),data[j+1][i+1]*zscale+bheight]])] o.facets+=[genfacet([[pscale*i, pscale*j, data[j][i]*zscale+bheight],[pscale*(i+1), pscale*(j), data[j][i+1]*zscale+bheight],[pscale*(i+1), pscale*(j+1), data[j+1][i+1]*zscale+bheight]])]
o.facets+=[genfacet([[pscale*(i),pscale*(j+1),data[j+1][i]*zscale+bheight],[pscale*i,pscale*j,data[j][i]*zscale+bheight],[pscale*(i+1),pscale*(j+1),data[j+1][i+1]*zscale+bheight]])] o.facets+=[genfacet([[pscale*(i), pscale*(j+1), data[j+1][i]*zscale+bheight],[pscale*i, pscale*j, data[j][i]*zscale+bheight],[pscale*(i+1), pscale*(j+1), data[j+1][i+1]*zscale+bheight]])]
#print o.facets[-1] #print o.facets[-1]
facet=[[0,0,0],[[0,0,0],[0,0,0],[0,0,0]]] facet = [[0, 0, 0],[[0, 0, 0],[0, 0, 0],[0, 0, 0]]]
return o return o
def zimage(name,out): def zimage(name, out):
i=wx.Image(name) i = wx.Image(name)
s=i.GetSize() s = i.GetSize()
print len(map(ord,i.GetData()[::3])) print len(map(ord, i.GetData()[::3]))
b=map(ord,i.GetData()[::3]) b = map(ord, i.GetData()[::3])
data=[] data = []
for i in xrange(s[0]): for i in xrange(s[0]):
data+=[b[i*s[1]:(i+1)*s[1]]] data+=[b[i*s[1]:(i+1)*s[1]]]
#data=[i[::5] for i in data[::5]] #data = [i[::5] for i in data[::5]]
emitstl(out,genscape(data,zscale=0.1).facets,name) emitstl(out, genscape(data, zscale = 0.1).facets, name)
""" """
class scapewin(wx.Frame): class scapewin(wx.Frame):
def __init__(self,size=(400,530)): def __init__(self, size = (400, 530)):
wx.Frame.__init__(self,None,title="Right-click to load an image",size=size) wx.Frame.__init__(self, None, title = "Right-click to load an image", size = size)
self.SetIcon(wx.Icon("plater.ico",wx.BITMAP_TYPE_ICO)) self.SetIcon(wx.Icon("plater.ico", wx.BITMAP_TYPE_ICO))
self.SetClientSize(size) self.SetClientSize(size)
self.panel=wx.Panel(self,size=size) self.panel = wx.Panel(self, size = size)
""" """
if __name__ == '__main__': if __name__ == '__main__':
...@@ -80,6 +80,5 @@ if __name__ == '__main__': ...@@ -80,6 +80,5 @@ if __name__ == '__main__':
main.Show() main.Show()
app.MainLoop() app.MainLoop()
""" """
zimage("catposthtmap2.jpg","testobj.stl") zimage("catposthtmap2.jpg", "testobj.stl")
del a del a
#!/usr/bin/env python #!/usr/bin/env python
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import cmd, sys import cmd, sys
import glob, os, time import glob, os, time, datetime
import sys, subprocess import sys, subprocess
import math, codecs import math, codecs
from math import sqrt from math import sqrt
from printrun import printcore import printcore
from printrun.printrun_utils import install_locale from printrun.printrun_utils import install_locale
install_locale('pronterface') install_locale('pronterface')
if os.name=="nt": if os.name == "nt":
try: try:
import _winreg import _winreg
except: except:
pass pass
READLINE=True READLINE = True
try: try:
import readline import readline
try: try:
readline.rl.mode.show_all_if_ambiguous="on" #config pyreadline on windows readline.rl.mode.show_all_if_ambiguous = "on" #config pyreadline on windows
except: except:
pass pass
except: except:
READLINE=False #neither readline module is available READLINE = False #neither readline module is available
def dosify(name): def dosify(name):
return os.path.split(name)[1].split(".")[0][:8]+".g" return os.path.split(name)[1].split(".")[0][:8]+".g"
def measurements(g): def measurements(g):
Xcur=0.0 Xcur = 0.0
Ycur=0.0 Ycur = 0.0
Zcur=0.0 Zcur = 0.0
Xmin=1000000 Xmin = 1000000
Ymin=1000000 Ymin = 1000000
Zmin=1000000 Zmin = 1000000
Xmax=-1000000 Xmax=-1000000
Ymax=-1000000 Ymax=-1000000
Zmax=-1000000 Zmax=-1000000
Xtot=0 Xtot = 0
Ytot=0 Ytot = 0
Ztot=0 Ztot = 0
for i in g: for i in g:
if "X" in i and ("G1" in i or "G0" in i): if "X" in i and ("G1" in i or "G0" in i):
try: try:
Xcur = float(i.split("X")[1].split(" ")[0]) Xcur = float(i.split("X")[1].split(" ")[0])
if Xcur<Xmin and Xcur>5.0: Xmin=Xcur if Xcur<Xmin and Xcur>5.0: Xmin = Xcur
if Xcur>Xmax: Xmax=Xcur if Xcur>Xmax: Xmax = Xcur
except: except:
pass pass
if "Y" in i and ("G1" in i or "G0" in i): if "Y" in i and ("G1" in i or "G0" in i):
try: try:
Ycur = float(i.split("Y")[1].split(" ")[0]) Ycur = float(i.split("Y")[1].split(" ")[0])
if Ycur<Ymin and Ycur>5.0: Ymin=Ycur if Ycur<Ymin and Ycur>5.0: Ymin = Ycur
if Ycur>Ymax: Ymax=Ycur if Ycur>Ymax: Ymax = Ycur
except: except:
pass pass
if "Z" in i and ("G1" in i or "G0" in i): if "Z" in i and ("G1" in i or "G0" in i):
try: try:
Zcur = float(i.split("Z")[1].split(" ")[0]) Zcur = float(i.split("Z")[1].split(" ")[0])
if Zcur<Zmin: Zmin=Zcur if Zcur<Zmin: Zmin = Zcur
if Zcur>Zmax: Zmax=Zcur if Zcur>Zmax: Zmax = Zcur
except: except:
pass pass
Xtot = Xmax - Xmin Xtot = Xmax - Xmin
Ytot = Ymax - Ymin Ytot = Ymax - Ymin
Ztot = Zmax - Zmin Ztot = Zmax - Zmin
return (Xtot,Ytot,Ztot,Xmin,Xmax,Ymin,Ymax,Zmin,Zmax) return (Xtot, Ytot, Ztot, Xmin, Xmax, Ymin, Ymax, Zmin, Zmax)
def totalelength(g): def totalelength(g):
tot=0 tot = 0
cur=0 cur = 0
for i in g: for i in g:
if "E" in i and ("G1" in i or "G0" in i): if "E" in i and ("G1" in i or "G0" in i):
try: try:
cur=float(i.split("E")[1].split(" ")[0]) cur = float(i.split("E")[1].split(" ")[0])
except: except:
pass pass
elif "G92" in i and "E0" in i: elif "G92" in i and "E0" in i:
...@@ -108,11 +108,11 @@ def get_coordinate_value(axis, parts): ...@@ -108,11 +108,11 @@ def get_coordinate_value(axis, parts):
return float(i[1:]) return float(i[1:])
return None return None
def hypot3d(X1, Y1, Z1, X2=0.0, Y2=0.0, Z2=0.0): def hypot3d(X1, Y1, Z1, X2 = 0.0, Y2 = 0.0, Z2 = 0.0):
return math.hypot(X2-X1, math.hypot(Y2-Y1, Z2-Z1)) return math.hypot(X2-X1, math.hypot(Y2-Y1, Z2-Z1))
def estimate_duration(g): def estimate_duration(g):
lastx = lasty = lastz = laste = lastf = 0.0 lastx = lasty = lastz = laste = lastf = 0.0
x = y = z = e = f = 0.0 x = y = z = e = f = 0.0
currenttravel = 0.0 currenttravel = 0.0
...@@ -122,13 +122,13 @@ def estimate_duration(g): ...@@ -122,13 +122,13 @@ def estimate_duration(g):
acceleration = 1500.0 #mm/s/s ASSUMING THE DEFAULT FROM SPRINTER !!!! acceleration = 1500.0 #mm/s/s ASSUMING THE DEFAULT FROM SPRINTER !!!!
layerduration = 0.0 layerduration = 0.0
layerbeginduration = 0.0 layerbeginduration = 0.0
layercount=0 layercount = 0
#TODO: #TODO:
# get device caps from firmware: max speed, acceleration/axis (including extruder) # get device caps from firmware: max speed, acceleration/axis (including extruder)
# calculate the maximum move duration accounting for above ;) # calculate the maximum move duration accounting for above ;)
# print ".... estimating ...." # print ".... estimating ...."
for i in g: for i in g:
i=i.split(";")[0] i = i.split(";")[0]
if "G4" in i or "G1" in i: if "G4" in i or "G1" in i:
if "G4" in i: if "G4" in i:
parts = i.split(" ") parts = i.split(" ")
...@@ -140,17 +140,17 @@ def estimate_duration(g): ...@@ -140,17 +140,17 @@ def estimate_duration(g):
if "G1" in i: if "G1" in i:
parts = i.split(" ") parts = i.split(" ")
x = get_coordinate_value("X", parts[1:]) x = get_coordinate_value("X", parts[1:])
if x is None: x=lastx if x is None: x = lastx
y = get_coordinate_value("Y", parts[1:]) y = get_coordinate_value("Y", parts[1:])
if y is None: y=lasty if y is None: y = lasty
z = get_coordinate_value("Z", parts[1:]) z = get_coordinate_value("Z", parts[1:])
if (z is None) or (z<lastz): z=lastz # Do not increment z if it's below the previous (Lift z on move fix) if (z is None) or (z<lastz): z = lastz # Do not increment z if it's below the previous (Lift z on move fix)
e = get_coordinate_value("E", parts[1:]) e = get_coordinate_value("E", parts[1:])
if e is None: e=laste if e is None: e = laste
f = get_coordinate_value("F", parts[1:]) f = get_coordinate_value("F", parts[1:])
if f is None: f=lastf if f is None: f = lastf
else: f /= 60.0 # mm/s vs mm/m else: f /= 60.0 # mm/s vs mm/m
# given last feedrate and current feedrate calculate the distance needed to achieve current feedrate. # given last feedrate and current feedrate calculate the distance needed to achieve current feedrate.
# if travel is longer than req'd distance, then subtract distance to achieve full speed, and add the time it took to get there. # if travel is longer than req'd distance, then subtract distance to achieve full speed, and add the time it took to get there.
# then calculate the time taken to complete the remaining distance # then calculate the time taken to complete the remaining distance
...@@ -178,13 +178,13 @@ def estimate_duration(g): ...@@ -178,13 +178,13 @@ def estimate_duration(g):
lastf = f lastf = f
#print "Total Duration: " #, time.strftime('%H:%M:%S', time.gmtime(totalduration)) #print "Total Duration: " #, time.strftime('%H:%M:%S', time.gmtime(totalduration))
return "{0:d} layers, ".format(int(layercount))+time.strftime('%H:%M:%S', time.gmtime(totalduration)) return "{0:d} layers, ".format(int(layercount)) + str(datetime.timedelta(seconds = int(totalduration)))
class Settings: class Settings:
#def _temperature_alias(self): return {"pla":210,"abs":230,"off":0} #def _temperature_alias(self): return {"pla":210, "abs":230, "off":0}
#def _temperature_validate(self,v): #def _temperature_validate(self, v):
# if v < 0: raise ValueError("You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0.") # if v < 0: raise ValueError("You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0.")
#def _bedtemperature_alias(self): return {"pla":60,"abs":110,"off":0} #def _bedtemperature_alias(self): return {"pla":60, "abs":110, "off":0}
def _baudrate_list(self): return ["2400", "9600", "19200", "38400", "57600", "115200"] def _baudrate_list(self): return ["2400", "9600", "19200", "38400", "57600", "115200"]
def __init__(self): def __init__(self):
# defaults here. # defaults here.
...@@ -198,70 +198,70 @@ class Settings: ...@@ -198,70 +198,70 @@ class Settings:
self.xy_feedrate = 3000 self.xy_feedrate = 3000
self.z_feedrate = 200 self.z_feedrate = 200
self.e_feedrate = 300 self.e_feedrate = 300
self.slicecommand="python skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py $s" self.slicecommand = "python skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py $s"
self.sliceoptscommand="python skeinforge/skeinforge_application/skeinforge.py" self.sliceoptscommand = "python skeinforge/skeinforge_application/skeinforge.py"
self.final_command = "" self.final_command = ""
def _set(self,key,value): def _set(self, key, value):
try: try:
value = getattr(self,"_%s_alias"%key)()[value] value = getattr(self, "_%s_alias"%key)()[value]
except KeyError: except KeyError:
pass pass
except AttributeError: except AttributeError:
pass pass
try: try:
getattr(self,"_%s_validate"%key)(value) getattr(self, "_%s_validate"%key)(value)
except AttributeError: except AttributeError:
pass pass
setattr(self,key,type(getattr(self,key))(value)) setattr(self, key, type(getattr(self, key))(value))
try: try:
getattr(self,"_%s_cb"%key)(key,value) getattr(self, "_%s_cb"%key)(key, value)
except AttributeError: except AttributeError:
pass pass
return value return value
def _tabcomplete(self,key): def _tabcomplete(self, key):
try: try:
return getattr(self,"_%s_list"%key)() return getattr(self, "_%s_list"%key)()
except AttributeError: except AttributeError:
pass pass
try: try:
return getattr(self,"_%s_alias"%key)().keys() return getattr(self, "_%s_alias"%key)().keys()
except AttributeError: except AttributeError:
pass pass
return [] return []
def _all_settings(self): def _all_settings(self):
return dict([(k,getattr(self,k)) for k in self.__dict__.keys() if not k.startswith("_")]) return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")])
class pronsole(cmd.Cmd): class pronsole(cmd.Cmd):
def __init__(self): def __init__(self):
cmd.Cmd.__init__(self) cmd.Cmd.__init__(self)
if not READLINE: if not READLINE:
self.completekey=None self.completekey = None
self.p=printcore.printcore() self.p = printcore.printcore()
self.p.recvcb=self.recvcb self.p.recvcb = self.recvcb
self.recvlisteners=[] self.recvlisteners = []
self.prompt="PC>" self.prompt = "PC>"
self.p.onlinecb=self.online self.p.onlinecb = self.online
self.f=None self.f = None
self.listing=0 self.listing = 0
self.sdfiles=[] self.sdfiles = []
self.paused=False self.paused = False
self.sdprinting=0 self.sdprinting = 0
self.temps={"pla":"185","abs":"230","off":"0"} self.temps = {"pla":"185", "abs":"230", "off":"0"}
self.bedtemps={"pla":"60","abs":"110","off":"0"} self.bedtemps = {"pla":"60", "abs":"110", "off":"0"}
self.percentdone=0 self.percentdone = 0
self.tempreadings="" self.tempreadings = ""
self.macros={} self.macros = {}
self.rc_loaded=False self.rc_loaded = False
self.processing_rc=False self.processing_rc = False
self.processing_args=False self.processing_args = False
self.settings = Settings() self.settings = Settings()
self.settings._port_list = self.scanserial self.settings._port_list = self.scanserial
self.settings._temperature_abs_cb = self.set_temp_preset self.settings._temperature_abs_cb = self.set_temp_preset
self.settings._temperature_pla_cb = self.set_temp_preset self.settings._temperature_pla_cb = self.set_temp_preset
self.settings._bedtemp_abs_cb = self.set_temp_preset self.settings._bedtemp_abs_cb = self.set_temp_preset
self.settings._bedtemp_pla_cb = self.set_temp_preset self.settings._bedtemp_pla_cb = self.set_temp_preset
self.monitoring=0 self.monitoring = 0
self.helpdict = {} self.helpdict = {}
self.helpdict["baudrate"] = _("Communications Speed (default: 115200)") self.helpdict["baudrate"] = _("Communications Speed (default: 115200)")
self.helpdict["bedtemp_abs"] = _("Heated Build Platform temp for ABS (default: 110 deg C)") self.helpdict["bedtemp_abs"] = _("Heated Build Platform temp for ABS (default: 110 deg C)")
...@@ -276,29 +276,29 @@ class pronsole(cmd.Cmd): ...@@ -276,29 +276,29 @@ class pronsole(cmd.Cmd):
self.helpdict["z_feedrate"] = _("Feedrate for Control Panel Moves in Z (default: 200mm/min)") self.helpdict["z_feedrate"] = _("Feedrate for Control Panel Moves in Z (default: 200mm/min)")
self.helpdict["final_command"] = _("Executable to run when the print is finished") self.helpdict["final_command"] = _("Executable to run when the print is finished")
self.commandprefixes='MGT$' self.commandprefixes='MGT$'
self.webrequested=False self.webrequested = False
self.web_config=None self.web_config = None
self.web_auth_config=None self.web_auth_config = None
def set_temp_preset(self,key,value): def set_temp_preset(self, key, value):
if not key.startswith("bed"): if not key.startswith("bed"):
self.temps["pla"] = str(self.settings.temperature_pla) self.temps["pla"] = str(self.settings.temperature_pla)
self.temps["abs"] = str(self.settings.temperature_abs) self.temps["abs"] = str(self.settings.temperature_abs)
print "Hotend temperature presets updated, pla:%s, abs:%s" % (self.temps["pla"],self.temps["abs"]) print "Hotend temperature presets updated, pla:%s, abs:%s" % (self.temps["pla"], self.temps["abs"])
else: else:
self.bedtemps["pla"] = str(self.settings.bedtemp_pla) self.bedtemps["pla"] = str(self.settings.bedtemp_pla)
self.bedtemps["abs"] = str(self.settings.bedtemp_abs) self.bedtemps["abs"] = str(self.settings.bedtemp_abs)
print "Bed temperature presets updated, pla:%s, abs:%s" % (self.bedtemps["pla"],self.bedtemps["abs"]) print "Bed temperature presets updated, pla:%s, abs:%s" % (self.bedtemps["pla"], self.bedtemps["abs"])
def scanserial(self): def scanserial(self):
"""scan for available ports. return a list of device names.""" """scan for available ports. return a list of device names."""
baselist=[] baselist = []
if os.name=="nt": if os.name == "nt":
try: try:
key=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM") key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM")
i=0 i = 0
while(1): while(1):
baselist+=[_winreg.EnumValue(key,i)[1]] baselist+=[_winreg.EnumValue(key, i)[1]]
i+=1 i+=1
except: except:
pass pass
...@@ -309,42 +309,42 @@ class pronsole(cmd.Cmd): ...@@ -309,42 +309,42 @@ class pronsole(cmd.Cmd):
print "Printer is now online" print "Printer is now online"
sys.stdout.write(self.prompt) sys.stdout.write(self.prompt)
sys.stdout.flush() sys.stdout.flush()
def help_help(self,l): def help_help(self, l):
self.do_help("") self.do_help("")
def do_gcodes(self,l): def do_gcodes(self, l):
self.help_gcodes() self.help_gcodes()
def help_gcodes(self): def help_gcodes(self):
print "Gcodes are passed through to the printer as they are" print "Gcodes are passed through to the printer as they are"
def complete_macro(self,text,line,begidx,endidx): def complete_macro(self, text, line, begidx, endidx):
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split()) == 2 and line[-1] != " ") or (len(line.split()) == 1 and line[-1]==" "):
return [i for i in self.macros.keys() if i.startswith(text)] return [i for i in self.macros.keys() if i.startswith(text)]
elif(len(line.split())==3 or (len(line.split())==2 and line[-1]==" ")): elif(len(line.split()) == 3 or (len(line.split()) == 2 and line[-1]==" ")):
return [i for i in ["/D", "/S"] + self.completenames(text) if i.startswith(text)] return [i for i in ["/D", "/S"] + self.completenames(text) if i.startswith(text)]
else: else:
return [] return []
def hook_macro(self,l): def hook_macro(self, l):
l = l.rstrip() l = l.rstrip()
ls = l.lstrip() ls = l.lstrip()
ws = l[:len(l)-len(ls)] # just leading whitespace ws = l[:len(l)-len(ls)] # just leading whitespace
if len(ws)==0: if len(ws) == 0:
self.end_macro() self.end_macro()
# pass the unprocessed line to regular command processor to not require empty line in .pronsolerc # pass the unprocessed line to regular command processor to not require empty line in .pronsolerc
return self.onecmd(l) return self.onecmd(l)
self.cur_macro_def += l + "\n" self.cur_macro_def += l + "\n"
def end_macro(self): def end_macro(self):
if self.__dict__.has_key("onecmd"): del self.onecmd # remove override if self.__dict__.has_key("onecmd"): del self.onecmd # remove override
self.prompt="PC>" self.prompt = "PC>"
if self.cur_macro_def!="": if self.cur_macro_def!="":
self.macros[self.cur_macro_name] = self.cur_macro_def self.macros[self.cur_macro_name] = self.cur_macro_def
macro = self.compile_macro(self.cur_macro_name,self.cur_macro_def) macro = self.compile_macro(self.cur_macro_name, self.cur_macro_def)
setattr(self.__class__,"do_"+self.cur_macro_name,lambda self,largs,macro=macro:macro(self,*largs.split())) setattr(self.__class__, "do_"+self.cur_macro_name, lambda self, largs, macro = macro:macro(self,*largs.split()))
setattr(self.__class__,"help_"+self.cur_macro_name,lambda self,macro_name=self.cur_macro_name: self.subhelp_macro(macro_name)) setattr(self.__class__, "help_"+self.cur_macro_name, lambda self, macro_name = self.cur_macro_name: self.subhelp_macro(macro_name))
if not self.processing_rc: if not self.processing_rc:
print "Macro '"+self.cur_macro_name+"' defined" print "Macro '"+self.cur_macro_name+"' defined"
# save it # save it
...@@ -356,22 +356,22 @@ class pronsole(cmd.Cmd): ...@@ -356,22 +356,22 @@ class pronsole(cmd.Cmd):
else: else:
macro_def += " " macro_def += " "
macro_def += self.cur_macro_def macro_def += self.cur_macro_def
self.save_in_rc(macro_key,macro_def) self.save_in_rc(macro_key, macro_def)
else: else:
print "Empty macro - cancelled" print "Empty macro - cancelled"
del self.cur_macro_name,self.cur_macro_def del self.cur_macro_name, self.cur_macro_def
def compile_macro_line(self,line): def compile_macro_line(self, line):
line = line.rstrip() line = line.rstrip()
ls = line.lstrip() ls = line.lstrip()
ws = line[:len(line)-len(ls)] # just leading whitespace ws = line[:len(line)-len(ls)] # just leading whitespace
if ls=="" or ls.startswith('#'): return "" # no code if ls == "" or ls.startswith('#'): return "" # no code
if ls.startswith('!'): if ls.startswith('!'):
return ws + ls[1:] + "\n" # python mode return ws + ls[1:] + "\n" # python mode
else: else:
return ws + 'self.onecmd("'+ls+'".format(*arg))\n' # parametric command mode return ws + 'self.onecmd("'+ls+'".format(*arg))\n' # parametric command mode
def compile_macro(self,macro_name,macro_def): def compile_macro(self, macro_name, macro_def):
if macro_def.strip() == "": if macro_def.strip() == "":
print "Empty macro - cancelled" print "Empty macro - cancelled"
return return
...@@ -384,31 +384,31 @@ class pronsole(cmd.Cmd): ...@@ -384,31 +384,31 @@ class pronsole(cmd.Cmd):
pycode += self.compile_macro_line(l) pycode += self.compile_macro_line(l)
exec pycode exec pycode
return macro return macro
def start_macro(self,macro_name,prev_definition="",suppress_instructions=False): def start_macro(self, macro_name, prev_definition = "", suppress_instructions = False):
if not self.processing_rc and not suppress_instructions: if not self.processing_rc and not suppress_instructions:
print "Enter macro using indented lines, end with empty line" print "Enter macro using indented lines, end with empty line"
self.cur_macro_name = macro_name self.cur_macro_name = macro_name
self.cur_macro_def = "" self.cur_macro_def = ""
self.onecmd = self.hook_macro # override onecmd temporarily self.onecmd = self.hook_macro # override onecmd temporarily
self.prompt="..>" self.prompt = "..>"
def delete_macro(self,macro_name): def delete_macro(self, macro_name):
if macro_name in self.macros.keys(): if macro_name in self.macros.keys():
delattr(self.__class__,"do_"+macro_name) delattr(self.__class__, "do_"+macro_name)
del self.macros[macro_name] del self.macros[macro_name]
print "Macro '"+macro_name+"' removed" print "Macro '"+macro_name+"' removed"
if not self.processing_rc and not self.processing_args: if not self.processing_rc and not self.processing_args:
self.save_in_rc("macro "+macro_name,"") self.save_in_rc("macro "+macro_name, "")
else: else:
print "Macro '"+macro_name+"' is not defined" print "Macro '"+macro_name+"' is not defined"
def do_macro(self,args): def do_macro(self, args):
if args.strip()=="": if args.strip()=="":
self.print_topics("User-defined macros",self.macros.keys(),15,80) self.print_topics("User-defined macros", self.macros.keys(), 15, 80)
return return
arglist = args.split(None,1) arglist = args.split(None, 1)
macro_name = arglist[0] macro_name = arglist[0]
if macro_name not in self.macros and hasattr(self.__class__,"do_"+macro_name): if macro_name not in self.macros and hasattr(self.__class__, "do_"+macro_name):
print "Name '"+macro_name+"' is being used by built-in command" print "Name '"+macro_name+"' is being used by built-in command"
return return
if len(arglist) == 2: if len(arglist) == 2:
...@@ -424,10 +424,10 @@ class pronsole(cmd.Cmd): ...@@ -424,10 +424,10 @@ class pronsole(cmd.Cmd):
self.end_macro() self.end_macro()
return return
if self.macros.has_key(macro_name): if self.macros.has_key(macro_name):
self.start_macro(macro_name,self.macros[macro_name]) self.start_macro(macro_name, self.macros[macro_name])
else: else:
self.start_macro(macro_name) self.start_macro(macro_name)
def help_macro(self): def help_macro(self):
print "Define single-line macro: macro <name> <definition>" print "Define single-line macro: macro <name> <definition>"
print "Define multi-line macro: macro <name>" print "Define multi-line macro: macro <name>"
...@@ -436,8 +436,8 @@ class pronsole(cmd.Cmd): ...@@ -436,8 +436,8 @@ class pronsole(cmd.Cmd):
print "Delete macro: macro <name> /d" print "Delete macro: macro <name> /d"
print "Show macro definition: macro <name> /s" print "Show macro definition: macro <name> /s"
print "'macro' without arguments displays list of defined macros" print "'macro' without arguments displays list of defined macros"
def subhelp_macro(self,macro_name): def subhelp_macro(self, macro_name):
if macro_name in self.macros.keys(): if macro_name in self.macros.keys():
macro_def = self.macros[macro_name] macro_def = self.macros[macro_name]
if "\n" in macro_def: if "\n" in macro_def:
...@@ -448,77 +448,77 @@ class pronsole(cmd.Cmd): ...@@ -448,77 +448,77 @@ class pronsole(cmd.Cmd):
else: else:
print "Macro '"+macro_name+"' is not defined" print "Macro '"+macro_name+"' is not defined"
def set(self,var,str): def set(self, var, str):
try: try:
t = type(getattr(self.settings,var)) t = type(getattr(self.settings, var))
value = self.settings._set(var,str) value = self.settings._set(var, str)
if not self.processing_rc and not self.processing_args: if not self.processing_rc and not self.processing_args:
self.save_in_rc("set "+var,"set %s %s" % (var,value)) self.save_in_rc("set "+var, "set %s %s" % (var, value))
except AttributeError: except AttributeError:
print "Unknown variable '%s'" % var print "Unknown variable '%s'" % var
except ValueError, ve: except ValueError, ve:
print "Bad value for variable '%s', expecting %s (%s)" % (var,repr(t)[1:-1],ve.args[0]) print "Bad value for variable '%s', expecting %s (%s)" % (var, repr(t)[1:-1], ve.args[0])
def do_set(self,argl): def do_set(self, argl):
args = argl.split(None,1) args = argl.split(None, 1)
if len(args) < 1: if len(args) < 1:
for k in [kk for kk in dir(self.settings) if not kk.startswith("_")]: for k in [kk for kk in dir(self.settings) if not kk.startswith("_")]:
print "%s = %s" % (k,str(getattr(self.settings,k))) print "%s = %s" % (k, str(getattr(self.settings, k)))
return return
value = getattr(self.settings,args[0]) value = getattr(self.settings, args[0])
if len(args) < 2: if len(args) < 2:
try: try:
print "%s = %s" % (args[0],getattr(self.settings,args[0])) print "%s = %s" % (args[0], getattr(self.settings, args[0]))
except AttributeError: except AttributeError:
print "Unknown variable '%s'" % args[0] print "Unknown variable '%s'" % args[0]
return return
self.set(args[0],args[1]) self.set(args[0], args[1])
def help_set(self): def help_set(self):
print "Set variable: set <variable> <value>" print "Set variable: set <variable> <value>"
print "Show variable: set <variable>" print "Show variable: set <variable>"
print "'set' without arguments displays all variables" print "'set' without arguments displays all variables"
def complete_set(self, text, line, begidx, endidx): def complete_set(self, text, line, begidx, endidx):
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split()) == 2 and line[-1] != " ") or (len(line.split()) == 1 and line[-1]==" "):
return [i for i in dir(self.settings) if not i.startswith("_") and i.startswith(text)] return [i for i in dir(self.settings) if not i.startswith("_") and i.startswith(text)]
elif(len(line.split())==3 or (len(line.split())==2 and line[-1]==" ")): elif(len(line.split()) == 3 or (len(line.split()) == 2 and line[-1]==" ")):
return [i for i in self.settings._tabcomplete(line.split()[1]) if i.startswith(text)] return [i for i in self.settings._tabcomplete(line.split()[1]) if i.startswith(text)]
else: else:
return [] return []
def postloop(self): def postloop(self):
self.p.disconnect() self.p.disconnect()
cmd.Cmd.postloop(self) cmd.Cmd.postloop(self)
def load_rc(self,rc_filename): def load_rc(self, rc_filename):
self.processing_rc=True self.processing_rc = True
try: try:
rc=codecs.open(rc_filename,"r","utf-8") rc = codecs.open(rc_filename, "r", "utf-8")
self.rc_filename = os.path.abspath(rc_filename) self.rc_filename = os.path.abspath(rc_filename)
for rc_cmd in rc: for rc_cmd in rc:
if not rc_cmd.lstrip().startswith("#"): if not rc_cmd.lstrip().startswith("#"):
self.onecmd(rc_cmd) self.onecmd(rc_cmd)
rc.close() rc.close()
if hasattr(self,"cur_macro_def"): if hasattr(self, "cur_macro_def"):
self.end_macro() self.end_macro()
self.rc_loaded = True self.rc_loaded = True
finally: finally:
self.processing_rc=False self.processing_rc = False
def load_default_rc(self,rc_filename=".pronsolerc"): def load_default_rc(self, rc_filename = ".pronsolerc"):
try: try:
try: try:
self.load_rc(os.path.join(os.path.expanduser("~"),rc_filename)) self.load_rc(os.path.join(os.path.expanduser("~"), rc_filename))
except IOError: except IOError:
self.load_rc(rc_filename) self.load_rc(rc_filename)
except IOError: except IOError:
# make sure the filename is initialized # make sure the filename is initialized
self.rc_filename = os.path.abspath(os.path.join(os.path.expanduser("~"),rc_filename)) self.rc_filename = os.path.abspath(os.path.join(os.path.expanduser("~"), rc_filename))
def save_in_rc(self,key,definition): def save_in_rc(self, key, definition):
""" """
Saves or updates macro or other definitions in .pronsolerc Saves or updates macro or other definitions in .pronsolerc
key is prefix that determines what is being defined/updated (e.g. 'macro foo') key is prefix that determines what is being defined/updated (e.g. 'macro foo')
definition is the full definition (that is written to file). (e.g. 'macro foo move x 10') definition is the full definition (that is written to file). (e.g. 'macro foo move x 10')
Set key as empty string to just add (and not overwrite) Set key as empty string to just add (and not overwrite)
...@@ -528,16 +528,16 @@ class pronsole(cmd.Cmd): ...@@ -528,16 +528,16 @@ class pronsole(cmd.Cmd):
Updates are made in the same file position. Updates are made in the same file position.
Additions are made to the end of the file. Additions are made to the end of the file.
""" """
rci,rco = None,None rci, rco = None, None
if definition != "" and not definition.endswith("\n"): if definition != "" and not definition.endswith("\n"):
definition += "\n" definition += "\n"
try: try:
written = False written = False
if os.path.exists(self.rc_filename): if os.path.exists(self.rc_filename):
import shutil import shutil
shutil.copy(self.rc_filename,self.rc_filename+"~bak") shutil.copy(self.rc_filename, self.rc_filename+"~bak")
rci=codecs.open(self.rc_filename+"~bak","r","utf-8") rci = codecs.open(self.rc_filename+"~bak", "r", "utf-8")
rco=codecs.open(self.rc_filename,"w","utf-8") rco = codecs.open(self.rc_filename, "w", "utf-8")
if rci is not None: if rci is not None:
overwriting = False overwriting = False
for rc_cmd in rci: for rc_cmd in rci:
...@@ -563,67 +563,67 @@ class pronsole(cmd.Cmd): ...@@ -563,67 +563,67 @@ class pronsole(cmd.Cmd):
#else: #else:
# print "Removed '"+key+"' from '"+self.rc_filename+"'" # print "Removed '"+key+"' from '"+self.rc_filename+"'"
except Exception, e: except Exception, e:
print "Saving failed for",key+":",str(e) print "Saving failed for", key+":", str(e)
finally: finally:
del rci,rco del rci, rco
def preloop(self): def preloop(self):
print "Welcome to the printer console! Type \"help\" for a list of available commands." print "Welcome to the printer console! Type \"help\" for a list of available commands."
cmd.Cmd.preloop(self) cmd.Cmd.preloop(self)
def do_connect(self,l): def do_connect(self, l):
a=l.split() a = l.split()
p=self.scanserial() p = self.scanserial()
port=self.settings.port port = self.settings.port
if (port == "" or port not in p) and len(p)>0: if (port == "" or port not in p) and len(p)>0:
port=p[0] port = p[0]
baud=self.settings.baudrate or 115200 baud = self.settings.baudrate or 115200
if(len(a)>0): if(len(a)>0):
port=a[0] port = a[0]
if(len(a)>1): if(len(a)>1):
try: try:
baud=int(a[1]) baud = int(a[1])
except: except:
print "Bad baud value '"+a[1]+"' ignored" print "Bad baud value '"+a[1]+"' ignored"
if len(p)==0 and not port: if len(p) == 0 and not port:
print "No serial ports detected - please specify a port" print "No serial ports detected - please specify a port"
return return
if len(a)==0: if len(a) == 0:
print "No port specified - connecting to %s at %dbps" % (port,baud) print "No port specified - connecting to %s at %dbps" % (port, baud)
if port != self.settings.port: if port != self.settings.port:
self.settings.port = port self.settings.port = port
self.save_in_rc("set port","set port %s" % port) self.save_in_rc("set port", "set port %s" % port)
if baud != self.settings.baudrate: if baud != self.settings.baudrate:
self.settings.baudrate = baud self.settings.baudrate = baud
self.save_in_rc("set baudrate","set baudrate %d" % baud) self.save_in_rc("set baudrate", "set baudrate %d" % baud)
self.p.connect(port, baud) self.p.connect(port, baud)
def help_connect(self): def help_connect(self):
print "Connect to printer" print "Connect to printer"
print "connect <port> <baudrate>" print "connect <port> <baudrate>"
print "If port and baudrate are not specified, connects to first detected port at 115200bps" print "If port and baudrate are not specified, connects to first detected port at 115200bps"
ports=self.scanserial() ports = self.scanserial()
if(len(ports)): if(len(ports)):
print "Available ports: ", " ".join(ports) print "Available ports: ", " ".join(ports)
else: else:
print "No serial ports were automatically found." print "No serial ports were automatically found."
def complete_connect(self, text, line, begidx, endidx): def complete_connect(self, text, line, begidx, endidx):
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split()) == 2 and line[-1] != " ") or (len(line.split()) == 1 and line[-1]==" "):
return [i for i in self.scanserial() if i.startswith(text)] return [i for i in self.scanserial() if i.startswith(text)]
elif(len(line.split())==3 or (len(line.split())==2 and line[-1]==" ")): elif(len(line.split()) == 3 or (len(line.split()) == 2 and line[-1]==" ")):
return [i for i in ["2400", "9600", "19200", "38400", "57600", "115200"] if i.startswith(text)] return [i for i in ["2400", "9600", "19200", "38400", "57600", "115200"] if i.startswith(text)]
else: else:
return [] return []
def do_disconnect(self,l): def do_disconnect(self, l):
self.p.disconnect() self.p.disconnect()
def help_disconnect(self): def help_disconnect(self):
print "Disconnects from the printer" print "Disconnects from the printer"
def do_load(self,l): def do_load(self,l):
self._do_load(l) self._do_load(l)
def _do_load(self,l): def _do_load(self,l):
if len(l)==0: if len(l)==0:
...@@ -633,26 +633,25 @@ class pronsole(cmd.Cmd): ...@@ -633,26 +633,25 @@ class pronsole(cmd.Cmd):
if not(os.path.exists(l)): if not(os.path.exists(l)):
print "File not found!" print "File not found!"
return return
self.f=[i.replace("\n","").replace("\r","") for i in open(l)] self.f = [i.replace("\n", "").replace("\r", "") for i in open(l)]
self.filename=l self.filename = l
print "Loaded ",l,", ",len(self.f)," lines." print "Loaded ", l, ", ", len(self.f)," lines."
def complete_load(self, text, line, begidx, endidx): def complete_load(self, text, line, begidx, endidx):
s=line.split() s = line.split()
if len(s)>2: if len(s)>2:
return [] return []
if (len(s)==1 and line[-1]==" ") or (len(s)==2 and line[-1]!=" "): if (len(s) == 1 and line[-1]==" ") or (len(s) == 2 and line[-1]!=" "):
if len(s)>1: if len(s)>1:
return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.g*")] return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.g*")]
else: else:
return glob.glob("*/")+glob.glob("*.g*") return glob.glob("*/")+glob.glob("*.g*")
def help_load(self): def help_load(self):
print "Loads a gcode file (with tab-completion)" print "Loads a gcode file (with tab-completion)"
def do_upload(self, l):
def do_upload(self,l): if len(l) == 0:
if len(l)==0:
print "No file name given." print "No file name given."
return return
print "Loading file:"+l.split()[0] print "Loading file:"+l.split()[0]
...@@ -662,16 +661,16 @@ class pronsole(cmd.Cmd): ...@@ -662,16 +661,16 @@ class pronsole(cmd.Cmd):
if not self.p.online: if not self.p.online:
print "Not connected to printer." print "Not connected to printer."
return return
self.f=[i.replace("\n","") for i in open(l.split()[0])] self.f = [i.replace("\n", "") for i in open(l.split()[0])]
self.filename=l.split()[0] self.filename = l.split()[0]
print "Loaded ",l,", ",len(self.f)," lines." print "Loaded ", l, ", ", len(self.f)," lines."
tname="" tname = ""
if len(l.split())>1: if len(l.split())>1:
tname=l.split()[1] tname = l.split()[1]
else: else:
print "please enter target name in 8.3 format." print "please enter target name in 8.3 format."
return return
print "Uploading as ",tname print "Uploading as ", tname
print("Uploading "+self.filename) print("Uploading "+self.filename)
self.p.send_now("M28 "+tname) self.p.send_now("M28 "+tname)
print("Press Ctrl-C to interrupt upload.") print("Press Ctrl-C to interrupt upload.")
...@@ -686,44 +685,43 @@ class pronsole(cmd.Cmd): ...@@ -686,44 +685,43 @@ class pronsole(cmd.Cmd):
sys.stdout.flush() sys.stdout.flush()
self.p.send_now("M29 "+tname) self.p.send_now("M29 "+tname)
self.sleep(0.2) self.sleep(0.2)
self.p.clear=1 self.p.clear = 1
self.listing=0 self.listing = 0
self.sdfiles=[] self.sdfiles = []
self.recvlisteners+=[self.listfiles] self.recvlisteners+=[self.listfiles]
self.p.send_now("M20") self.p.send_now("M20")
time.sleep(0.5) time.sleep(0.5)
print "\b\b\b\b\b100%. Upload completed. ",tname," should now be on the card." print "\b\b\b\b\b100%. Upload completed. ", tname, " should now be on the card."
return return
except: except:
print "...interrupted!" print "...interrupted!"
self.p.pause() self.p.pause()
self.p.send_now("M29 "+tname) self.p.send_now("M29 "+tname)
time.sleep(0.2) time.sleep(0.2)
self.p.clear=1 self.p.clear = 1
self.p.startprint([]) self.p.startprint([])
print "A partial file named ",tname," may have been written to the sd card." print "A partial file named ", tname, " may have been written to the sd card."
def complete_upload(self, text, line, begidx, endidx): def complete_upload(self, text, line, begidx, endidx):
s=line.split() s = line.split()
if len(s)>2: if len(s)>2:
return [] return []
if (len(s)==1 and line[-1]==" ") or (len(s)==2 and line[-1]!=" "): if (len(s) == 1 and line[-1]==" ") or (len(s) == 2 and line[-1]!=" "):
if len(s)>1: if len(s)>1:
return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.g*")] return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.g*")]
else: else:
return glob.glob("*/")+glob.glob("*.g*") return glob.glob("*/")+glob.glob("*.g*")
def help_upload(self): def help_upload(self):
print "Uploads a gcode file to the sd card" print "Uploads a gcode file to the sd card"
def help_print(self): def help_print(self):
if self.f is None: if self.f is None:
print "Send a loaded gcode file to the printer. Load a file with the load command first." print "Send a loaded gcode file to the printer. Load a file with the load command first."
else: else:
print "Send a loaded gcode file to the printer. You have "+self.filename+" loaded right now." print "Send a loaded gcode file to the printer. You have "+self.filename+" loaded right now."
def do_print(self, l): def do_print(self, l):
if self.f is None: if self.f is None:
print "No file loaded. Please use load first." print "No file loaded. Please use load first."
...@@ -735,10 +733,10 @@ class pronsole(cmd.Cmd): ...@@ -735,10 +733,10 @@ class pronsole(cmd.Cmd):
print("You can monitor the print with the monitor command.") print("You can monitor the print with the monitor command.")
self.p.startprint(self.f) self.p.startprint(self.f)
#self.p.pause() #self.p.pause()
#self.paused=True #self.paused = True
#self.do_resume(None) #self.do_resume(None)
def do_pause(self,l): def do_pause(self, l):
if self.sdprinting: if self.sdprinting:
self.p.send_now("M25") self.p.send_now("M25")
else: else:
...@@ -746,58 +744,58 @@ class pronsole(cmd.Cmd): ...@@ -746,58 +744,58 @@ class pronsole(cmd.Cmd):
print "Not printing, cannot pause." print "Not printing, cannot pause."
return return
self.p.pause() self.p.pause()
#self.p.connect()# This seems to work, but is not a good solution. #self.p.connect()# This seems to work, but is not a good solution.
self.paused=True self.paused = True
#self.do_resume(None) #self.do_resume(None)
def help_pause(self): def help_pause(self):
print "Pauses a running print" print "Pauses a running print"
def do_resume(self,l): def do_resume(self, l):
if not self.paused: if not self.paused:
print "Not paused, unable to resume. Start a print first." print "Not paused, unable to resume. Start a print first."
return return
self.paused=False self.paused = False
if self.sdprinting: if self.sdprinting:
self.p.send_now("M24") self.p.send_now("M24")
return return
else: else:
self.p.resume() self.p.resume()
def help_resume(self): def help_resume(self):
print "Resumes a paused print." print "Resumes a paused print."
def emptyline(self): def emptyline(self):
pass pass
def do_shell(self,l): def do_shell(self, l):
exec(l) exec(l)
def listfiles(self,line): def listfiles(self, line):
if "Begin file list" in line: if "Begin file list" in line:
self.listing=1 self.listing = 1
elif "End file list" in line: elif "End file list" in line:
self.listing=0 self.listing = 0
self.recvlisteners.remove(self.listfiles) self.recvlisteners.remove(self.listfiles)
elif self.listing: elif self.listing:
self.sdfiles+=[line.replace("\n","").replace("\r","").lower()] self.sdfiles+=[line.replace("\n", "").replace("\r", "").lower()]
def do_ls(self,l): def do_ls(self, l):
if not self.p.online: if not self.p.online:
print "Printer is not online. Try connect to it first." print "Printer is not online. Try connect to it first."
return return
self.listing=2 self.listing = 2
self.sdfiles=[] self.sdfiles = []
self.recvlisteners+=[self.listfiles] self.recvlisteners+=[self.listfiles]
self.p.send_now("M20") self.p.send_now("M20")
time.sleep(0.5) time.sleep(0.5)
print " ".join(self.sdfiles) print " ".join(self.sdfiles)
def help_ls(self): def help_ls(self):
print "lists files on the SD card" print "lists files on the SD card"
def waitforsdresponse(self,l): def waitforsdresponse(self, l):
if "file.open failed" in l: if "file.open failed" in l:
print "Opening file failed." print "Opening file failed."
self.recvlisteners.remove(self.waitforsdresponse) self.recvlisteners.remove(self.waitforsdresponse)
...@@ -807,35 +805,35 @@ class pronsole(cmd.Cmd): ...@@ -807,35 +805,35 @@ class pronsole(cmd.Cmd):
if "File selected" in l: if "File selected" in l:
print "Starting print" print "Starting print"
self.p.send_now("M24") self.p.send_now("M24")
self.sdprinting=1 self.sdprinting = 1
#self.recvlisteners.remove(self.waitforsdresponse) #self.recvlisteners.remove(self.waitforsdresponse)
return return
if "Done printing file" in l: if "Done printing file" in l:
print l print l
self.sdprinting=0 self.sdprinting = 0
self.recvlisteners.remove(self.waitforsdresponse) self.recvlisteners.remove(self.waitforsdresponse)
return return
if "SD printing byte" in l: if "SD printing byte" in l:
#M27 handler #M27 handler
try: try:
resp=l.split() resp = l.split()
vals=resp[-1].split("/") vals = resp[-1].split("/")
self.percentdone=100.0*int(vals[0])/int(vals[1]) self.percentdone = 100.0*int(vals[0])/int(vals[1])
except: except:
pass pass
def do_reset(self,l): def do_reset(self, l):
self.p.reset() self.p.reset()
def help_reset(self): def help_reset(self):
print "Resets the printer." print "Resets the printer."
def do_sdprint(self,l): def do_sdprint(self, l):
if not self.p.online: if not self.p.online:
print "Printer is not online. Try connect to it first." print "Printer is not online. Try connect to it first."
return return
self.listing=2 self.listing = 2
self.sdfiles=[] self.sdfiles = []
self.recvlisteners+=[self.listfiles] self.recvlisteners+=[self.listfiles]
self.p.send_now("M20") self.p.send_now("M20")
time.sleep(0.5) time.sleep(0.5)
...@@ -847,36 +845,36 @@ class pronsole(cmd.Cmd): ...@@ -847,36 +845,36 @@ class pronsole(cmd.Cmd):
print "Printing file: "+l.lower()+" from SD card." print "Printing file: "+l.lower()+" from SD card."
print "Requesting SD print..." print "Requesting SD print..."
time.sleep(1) time.sleep(1)
def help_sdprint(self): def help_sdprint(self):
print "Print a file from the SD card. Tabcompletes with available file names." print "Print a file from the SD card. Tabcompletes with available file names."
print "sdprint filename.g" print "sdprint filename.g"
def complete_sdprint(self, text, line, begidx, endidx): def complete_sdprint(self, text, line, begidx, endidx):
if self.sdfiles==[] and self.p.online: if self.sdfiles==[] and self.p.online:
self.listing=2 self.listing = 2
self.recvlisteners+=[self.listfiles] self.recvlisteners+=[self.listfiles]
self.p.send_now("M20") self.p.send_now("M20")
time.sleep(0.5) time.sleep(0.5)
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split()) == 2 and line[-1] != " ") or (len(line.split()) == 1 and line[-1]==" "):
return [i for i in self.sdfiles if i.startswith(text)] return [i for i in self.sdfiles if i.startswith(text)]
def recvcb(self,l): def recvcb(self, l):
if "T:" in l: if "T:" in l:
self.tempreadings=l self.tempreadings = l
tstring=l.rstrip() tstring = l.rstrip()
if(tstring!="ok" and not tstring.startswith("ok T") and not tstring.startswith("T:") and not self.listing and not self.monitoring): if(tstring!="ok" and not tstring.startswith("ok T") and not tstring.startswith("T:") and not self.listing and not self.monitoring):
print tstring print tstring
sys.stdout.write(self.prompt) sys.stdout.write(self.prompt)
sys.stdout.flush() sys.stdout.flush()
for i in self.recvlisteners: for i in self.recvlisteners:
i(l) i(l)
def help_shell(self): def help_shell(self):
print "Executes a python command. Example:" print "Executes a python command. Example:"
print "! os.listdir('.')" print "! os.listdir('.')"
def default(self,l): def default(self, l):
if(l[0] in self.commandprefixes.upper()): if(l[0] in self.commandprefixes.upper()):
if(self.p and self.p.online): if(self.p and self.p.online):
if(not self.p.loud): if(not self.p.loud):
...@@ -894,78 +892,78 @@ class pronsole(cmd.Cmd): ...@@ -894,78 +892,78 @@ class pronsole(cmd.Cmd):
print "Printer is not online." print "Printer is not online."
return return
else: else:
cmd.Cmd.default(self,l) cmd.Cmd.default(self, l)
def help_help(self): def help_help(self):
self.do_help("") self.do_help("")
def tempcb(self,l): def tempcb(self, l):
if "T:" in l: if "T:" in l:
print l.replace("\r","").replace("T","Hotend").replace("B","Bed").replace("\n","").replace("ok ","") print l.replace("\r", "").replace("T", "Hotend").replace("B", "Bed").replace("\n", "").replace("ok ", "")
def do_gettemp(self,l): def do_gettemp(self, l):
if self.p.online: if self.p.online:
self.recvlisteners+=[self.tempcb] self.recvlisteners+=[self.tempcb]
self.p.send_now("M105") self.p.send_now("M105")
time.sleep(0.75) time.sleep(0.75)
self.recvlisteners.remove(self.tempcb) self.recvlisteners.remove(self.tempcb)
def help_gettemp(self): def help_gettemp(self):
print "Read the extruder and bed temperature." print "Read the extruder and bed temperature."
def do_settemp(self,l): def do_settemp(self, l):
try: try:
l=l.lower().replace(",",".") l = l.lower().replace(", ",".")
for i in self.temps.keys(): for i in self.temps.keys():
l=l.replace(i,self.temps[i]) l = l.replace(i, self.temps[i])
f=float(l) f = float(l)
if f>=0: if f>=0:
if self.p.online: if self.p.online:
self.p.send_now("M104 S"+l) self.p.send_now("M104 S"+l)
print "Setting hotend temperature to ",f," degrees Celsius." print "Setting hotend temperature to ", f, " degrees Celsius."
else: else:
print "Printer is not online." print "Printer is not online."
else: else:
print "You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0." print "You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0."
except: except:
print "You must enter a temperature." print "You must enter a temperature."
def help_settemp(self): def help_settemp(self):
print "Sets the hotend temperature to the value entered." print "Sets the hotend temperature to the value entered."
print "Enter either a temperature in celsius or one of the following keywords" print "Enter either a temperature in celsius or one of the following keywords"
print ", ".join([i+"("+self.temps[i]+")" for i in self.temps.keys()]) print ", ".join([i+"("+self.temps[i]+")" for i in self.temps.keys()])
def complete_settemp(self, text, line, begidx, endidx): def complete_settemp(self, text, line, begidx, endidx):
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split()) == 2 and line[-1] != " ") or (len(line.split()) == 1 and line[-1]==" "):
return [i for i in self.temps.keys() if i.startswith(text)] return [i for i in self.temps.keys() if i.startswith(text)]
def do_bedtemp(self,l): def do_bedtemp(self, l):
try: try:
l=l.lower().replace(",",".") l = l.lower().replace(", ",".")
for i in self.bedtemps.keys(): for i in self.bedtemps.keys():
l=l.replace(i,self.bedtemps[i]) l = l.replace(i, self.bedtemps[i])
f=float(l) f = float(l)
if f>=0: if f>=0:
if self.p.online: if self.p.online:
self.p.send_now("M140 S"+l) self.p.send_now("M140 S"+l)
print "Setting bed temperature to ",f," degrees Celsius." print "Setting bed temperature to ", f, " degrees Celsius."
else: else:
print "Printer is not online." print "Printer is not online."
else: else:
print "You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0." print "You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0."
except: except:
print "You must enter a temperature." print "You must enter a temperature."
def help_bedtemp(self): def help_bedtemp(self):
print "Sets the bed temperature to the value entered." print "Sets the bed temperature to the value entered."
print "Enter either a temperature in celsius or one of the following keywords" print "Enter either a temperature in celsius or one of the following keywords"
print ", ".join([i+"("+self.bedtemps[i]+")" for i in self.bedtemps.keys()]) print ", ".join([i+"("+self.bedtemps[i]+")" for i in self.bedtemps.keys()])
def complete_bedtemp(self, text, line, begidx, endidx): def complete_bedtemp(self, text, line, begidx, endidx):
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split()) == 2 and line[-1] != " ") or (len(line.split()) == 1 and line[-1]==" "):
return [i for i in self.bedtemps.keys() if i.startswith(text)] return [i for i in self.bedtemps.keys() if i.startswith(text)]
def do_move(self,l): def do_move(self, l):
if(len(l.split())<2): if(len(l.split())<2):
print "No move specified." print "No move specified."
return return
...@@ -975,80 +973,80 @@ class pronsole(cmd.Cmd): ...@@ -975,80 +973,80 @@ class pronsole(cmd.Cmd):
if not self.p.online: if not self.p.online:
print "Printer is not online. Unable to move." print "Printer is not online. Unable to move."
return return
l=l.split() l = l.split()
if(l[0].lower()=="x"): if(l[0].lower()=="x"):
feed=self.settings.xy_feedrate feed = self.settings.xy_feedrate
axis="X" axis = "X"
elif(l[0].lower()=="y"): elif(l[0].lower()=="y"):
feed=self.settings.xy_feedrate feed = self.settings.xy_feedrate
axis="Y" axis = "Y"
elif(l[0].lower()=="z"): elif(l[0].lower()=="z"):
feed=self.settings.z_feedrate feed = self.settings.z_feedrate
axis="Z" axis = "Z"
elif(l[0].lower()=="e"): elif(l[0].lower()=="e"):
feed=self.settings.e_feedrate feed = self.settings.e_feedrate
axis="E" axis = "E"
else: else:
print "Unknown axis." print "Unknown axis."
return return
dist=0 dist = 0
try: try:
dist=float(l[1]) dist = float(l[1])
except: except:
print "Invalid distance" print "Invalid distance"
return return
try: try:
feed=int(l[2]) feed = int(l[2])
except: except:
pass pass
self.p.send_now("G91") self.p.send_now("G91")
self.p.send_now("G1 "+axis+str(l[1])+" F"+str(feed)) self.p.send_now("G1 "+axis+str(l[1])+" F"+str(feed))
self.p.send_now("G90") self.p.send_now("G90")
def help_move(self): def help_move(self):
print "Move an axis. Specify the name of the axis and the amount. " print "Move an axis. Specify the name of the axis and the amount. "
print "move X 10 will move the X axis forward by 10mm at ",self.settings.xy_feedrate,"mm/min (default XY speed)" print "move X 10 will move the X axis forward by 10mm at ", self.settings.xy_feedrate, "mm/min (default XY speed)"
print "move Y 10 5000 will move the Y axis forward by 10mm at 5000mm/min" print "move Y 10 5000 will move the Y axis forward by 10mm at 5000mm/min"
print "move Z -1 will move the Z axis down by 1mm at ",self.settings.z_feedrate,"mm/min (default Z speed)" print "move Z -1 will move the Z axis down by 1mm at ", self.settings.z_feedrate, "mm/min (default Z speed)"
print "Common amounts are in the tabcomplete list." print "Common amounts are in the tabcomplete list."
def complete_move(self, text, line, begidx, endidx): def complete_move(self, text, line, begidx, endidx):
if (len(line.split())==2 and line[-1] != " ") or (len(line.split())==1 and line[-1]==" "): if (len(line.split()) == 2 and line[-1] != " ") or (len(line.split()) == 1 and line[-1]==" "):
return [i for i in ["X ","Y ","Z ","E "] if i.lower().startswith(text)] return [i for i in ["X ", "Y ", "Z ", "E "] if i.lower().startswith(text)]
elif(len(line.split())==3 or (len(line.split())==2 and line[-1]==" ")): elif(len(line.split()) == 3 or (len(line.split()) == 2 and line[-1]==" ")):
base=line.split()[-1] base = line.split()[-1]
rlen=0 rlen = 0
if base.startswith("-"): if base.startswith("-"):
rlen=1 rlen = 1
if line[-1]==" ": if line[-1]==" ":
base="" base = ""
return [i[rlen:] for i in ["-100","-10","-1","-0.1","100","10","1","0.1","-50","-5","-0.5","50","5","0.5","-200","-20","-2","-0.2","200","20","2","0.2"] if i.startswith(base)] return [i[rlen:] for i in ["-100", "-10", "-1", "-0.1", "100", "10", "1", "0.1", "-50", "-5", "-0.5", "50", "5", "0.5", "-200", "-20", "-2", "-0.2", "200", "20", "2", "0.2"] if i.startswith(base)]
else: else:
return [] return []
def do_extrude(self,l,override=None,overridefeed=300): def do_extrude(self, l, override = None, overridefeed = 300):
length=5#default extrusion length length = 5#default extrusion length
feed=self.settings.e_feedrate#default speed feed = self.settings.e_feedrate#default speed
if not self.p.online: if not self.p.online:
print "Printer is not online. Unable to move." print "Printer is not online. Unable to move."
return return
if self.p.printing: if self.p.printing:
print "Printer is currently printing. Please pause the print before you issue manual commands." print "Printer is currently printing. Please pause the print before you issue manual commands."
return return
ls=l.split() ls = l.split()
if len(ls): if len(ls):
try: try:
length=float(ls[0]) length = float(ls[0])
except: except:
print "Invalid length given." print "Invalid length given."
if len(ls)>1: if len(ls)>1:
try: try:
feed=int(ls[1]) feed = int(ls[1])
except: except:
print "Invalid speed given." print "Invalid speed given."
if override is not None: if override is not None:
length=override length = override
feed=overridefeed feed = overridefeed
if length > 0: if length > 0:
print "Extruding %fmm of filament."%(length,) print "Extruding %fmm of filament."%(length,)
elif length <0: elif length <0:
...@@ -1058,99 +1056,99 @@ class pronsole(cmd.Cmd): ...@@ -1058,99 +1056,99 @@ class pronsole(cmd.Cmd):
self.p.send_now("G91") self.p.send_now("G91")
self.p.send_now("G1 E"+str(length)+" F"+str(feed)) self.p.send_now("G1 E"+str(length)+" F"+str(feed))
self.p.send_now("G90") self.p.send_now("G90")
def help_extrude(self): def help_extrude(self):
print "Extrudes a length of filament, 5mm by default, or the number of mm given as a parameter" print "Extrudes a length of filament, 5mm by default, or the number of mm given as a parameter"
print "extrude - extrudes 5mm of filament at 300mm/min (5mm/s)" print "extrude - extrudes 5mm of filament at 300mm/min (5mm/s)"
print "extrude 20 - extrudes 20mm of filament at 300mm/min (5mm/s)" print "extrude 20 - extrudes 20mm of filament at 300mm/min (5mm/s)"
print "extrude -5 - REVERSES 5mm of filament at 300mm/min (5mm/s)" print "extrude -5 - REVERSES 5mm of filament at 300mm/min (5mm/s)"
print "extrude 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s)" print "extrude 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s)"
def do_reverse(self, l): def do_reverse(self, l):
length=5#default extrusion length length = 5#default extrusion length
feed=self.settings.e_feedrate#default speed feed = self.settings.e_feedrate#default speed
if not self.p.online: if not self.p.online:
print "Printer is not online. Unable to move." print "Printer is not online. Unable to move."
return return
if self.p.printing: if self.p.printing:
print "Printer is currently printing. Please pause the print before you issue manual commands." print "Printer is currently printing. Please pause the print before you issue manual commands."
return return
ls=l.split() ls = l.split()
if len(ls): if len(ls):
try: try:
length=float(ls[0]) length = float(ls[0])
except: except:
print "Invalid length given." print "Invalid length given."
if len(ls)>1: if len(ls)>1:
try: try:
feed=int(ls[1]) feed = int(ls[1])
except: except:
print "Invalid speed given." print "Invalid speed given."
self.do_extrude("",length*-1.0,feed) self.do_extrude("", length*-1.0, feed)
def help_reverse(self): def help_reverse(self):
print "Reverses the extruder, 5mm by default, or the number of mm given as a parameter" print "Reverses the extruder, 5mm by default, or the number of mm given as a parameter"
print "reverse - reverses 5mm of filament at 300mm/min (5mm/s)" print "reverse - reverses 5mm of filament at 300mm/min (5mm/s)"
print "reverse 20 - reverses 20mm of filament at 300mm/min (5mm/s)" print "reverse 20 - reverses 20mm of filament at 300mm/min (5mm/s)"
print "reverse 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s)" print "reverse 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s)"
print "reverse -5 - EXTRUDES 5mm of filament at 300mm/min (5mm/s)" print "reverse -5 - EXTRUDES 5mm of filament at 300mm/min (5mm/s)"
def do_exit(self,l): def do_exit(self, l):
print "Disconnecting from printer..." print "Disconnecting from printer..."
self.p.disconnect() self.p.disconnect()
print "Exiting program. Goodbye!" print "Exiting program. Goodbye!"
return True return True
def help_exit(self): def help_exit(self):
print "Disconnects from the printer and exits the program." print "Disconnects from the printer and exits the program."
def do_monitor(self,l): def do_monitor(self, l):
interval=5 interval = 5
if not self.p.online: if not self.p.online:
print "Printer is not online. Please connect first." print "Printer is not online. Please connect first."
return return
print "Monitoring printer, use ^C to interrupt." print "Monitoring printer, use ^C to interrupt."
if len(l): if len(l):
try: try:
interval=float(l) interval = float(l)
except: except:
print "Invalid period given." print "Invalid period given."
print "Updating values every %f seconds."%(interval,) print "Updating values every %f seconds."%(interval,)
self.monitoring=1 self.monitoring = 1
try: try:
while(1): while(1):
self.p.send_now("M105") self.p.send_now("M105")
if(self.sdprinting): if(self.sdprinting):
self.p.send_now("M27") self.p.send_now("M27")
time.sleep(interval) time.sleep(interval)
#print (self.tempreadings.replace("\r","").replace("T","Hotend").replace("B","Bed").replace("\n","").replace("ok ","")) #print (self.tempreadings.replace("\r", "").replace("T", "Hotend").replace("B", "Bed").replace("\n", "").replace("ok ", ""))
if(self.p.printing): if(self.p.printing):
print "Print progress: ", 100*float(self.p.queueindex)/len(self.p.mainqueue), "%" print "Print progress: ", 100*float(self.p.queueindex)/len(self.p.mainqueue), "%"
if(self.sdprinting): if(self.sdprinting):
print "SD print progress: ", self.percentdone,"%" print "SD print progress: ", self.percentdone, "%"
except: except:
print "Done monitoring." print "Done monitoring."
pass pass
self.monitoring=0 self.monitoring = 0
def help_monitor(self): def help_monitor(self):
print "Monitor a machine's temperatures and an SD print's status." print "Monitor a machine's temperatures and an SD print's status."
print "monitor - Reports temperature and SD print status (if SD printing) every 5 seconds" print "monitor - Reports temperature and SD print status (if SD printing) every 5 seconds"
print "monitor 2 - Reports temperature and SD print status (if SD printing) every 2 seconds" print "monitor 2 - Reports temperature and SD print status (if SD printing) every 2 seconds"
def expandcommand(self,c): def expandcommand(self, c):
return c.replace("$python",sys.executable) return c.replace("$python", sys.executable)
def do_skein(self,l): def do_skein(self, l):
l=l.split() l = l.split()
if len(l)==0: if len(l) == 0:
print "No file name given." print "No file name given."
return return
settings=0 settings = 0
if(l[0]=="set"): if(l[0]=="set"):
settings=1 settings = 1
else: else:
print "Skeining file:"+l[0] print "Skeining file:"+l[0]
if not(os.path.exists(l[0])): if not(os.path.exists(l[0])):
...@@ -1159,37 +1157,37 @@ class pronsole(cmd.Cmd): ...@@ -1159,37 +1157,37 @@ class pronsole(cmd.Cmd):
try: try:
import shlex import shlex
if(settings): if(settings):
param = self.expandcommand(self.settings.sliceoptscommand).replace("\\","\\\\").encode() param = self.expandcommand(self.settings.sliceoptscommand).replace("\\", "\\\\").encode()
print "Entering slicer settings: ",param print "Entering slicer settings: ", param
subprocess.call(shlex.split(param)) subprocess.call(shlex.split(param))
else: else:
param = self.expandcommand(self.settings.slicecommand).encode() param = self.expandcommand(self.settings.slicecommand).encode()
print "Slicing: ",param print "Slicing: ", param
params=[i.replace("$s",l[0]).replace("$o",l[0].replace(".stl","_export.gcode").replace(".STL","_export.gcode")).encode() for i in shlex.split(param.replace("\\","\\\\").encode())] params = [i.replace("$s", l[0]).replace("$o", l[0].replace(".stl", "_export.gcode").replace(".STL", "_export.gcode")).encode() for i in shlex.split(param.replace("\\", "\\\\").encode())]
subprocess.call(params) subprocess.call(params)
print "Loading sliced file." print "Loading sliced file."
self.do_load(l[0].replace(".stl","_export.gcode")) self.do_load(l[0].replace(".stl", "_export.gcode"))
except Exception,e: except Exception, e:
print "Skeinforge execution failed: ",e print "Skeinforge execution failed: ", e
def complete_skein(self, text, line, begidx, endidx): def complete_skein(self, text, line, begidx, endidx):
s=line.split() s = line.split()
if len(s)>2: if len(s)>2:
return [] return []
if (len(s)==1 and line[-1]==" ") or (len(s)==2 and line[-1]!=" "): if (len(s) == 1 and line[-1]==" ") or (len(s) == 2 and line[-1]!=" "):
if len(s)>1: if len(s)>1:
return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.stl")] return [i[len(s[1])-len(text):] for i in glob.glob(s[1]+"*/")+glob.glob(s[1]+"*.stl")]
else: else:
return glob.glob("*/")+glob.glob("*.stl") return glob.glob("*/")+glob.glob("*.stl")
def help_skein(self): def help_skein(self):
print "Creates a gcode file from an stl model using the slicer (with tab-completion)" print "Creates a gcode file from an stl model using the slicer (with tab-completion)"
print "skein filename.stl - create gcode file" print "skein filename.stl - create gcode file"
print "skein filename.stl view - create gcode file and view using skeiniso" print "skein filename.stl view - create gcode file and view using skeiniso"
print "skein set - adjust slicer settings" print "skein set - adjust slicer settings"
def do_home(self,l): def do_home(self, l):
if not self.p.online: if not self.p.online:
print "Printer is not online. Unable to move." print "Printer is not online. Unable to move."
return return
...@@ -1207,7 +1205,7 @@ class pronsole(cmd.Cmd): ...@@ -1207,7 +1205,7 @@ class pronsole(cmd.Cmd):
if not len(l): if not len(l):
self.p.send_now("G28") self.p.send_now("G28")
self.p.send_now("G92 E0") self.p.send_now("G92 E0")
def help_home(self): def help_home(self):
print "Homes the printer" print "Homes the printer"
print "home - homes all axes and zeroes the extruder(Using G28 and G92)" print "home - homes all axes and zeroes the extruder(Using G28 and G92)"
...@@ -1215,21 +1213,21 @@ class pronsole(cmd.Cmd): ...@@ -1215,21 +1213,21 @@ class pronsole(cmd.Cmd):
print "home z - homes z axis only (Using G28)" print "home z - homes z axis only (Using G28)"
print "home e - set extruder position to zero (Using G92)" print "home e - set extruder position to zero (Using G92)"
print "home xyze - homes all axes and zeroes the extruder (Using G28 and G92)" print "home xyze - homes all axes and zeroes the extruder (Using G28 and G92)"
def parse_cmdline(self,args): def parse_cmdline(self, args):
import getopt import getopt
opts,args = getopt.getopt(args, "c:e:hw", ["conf=","config=","help","web","web-config=", "web-auth-config="]) opts, args = getopt.getopt(args, "c:e:hw", ["conf = ", "config = ", "help", "web", "web-config = ", "web-auth-config = "])
for o,a in opts: for o, a in opts:
#print repr((o,a)) #print repr((o, a))
if o in ("-c","--conf","--config"): if o in ("-c", "--conf", "--config"):
self.load_rc(a) self.load_rc(a)
elif o in ("-w","--web"): elif o in ("-w", "--web"):
self.webrequested = True self.webrequested = True
elif o == "--web-config": elif o == "--web-config":
self.web_config = a self.web_config = a
elif o == "--web-auth-config": elif o == "--web-auth-config":
self.web_auth_config = a self.web_auth_config = a
elif o in ("-h","--help"): elif o in ("-h", "--help"):
print "Usage: "+sys.argv[0]+' [-c filename [-c filename2 ... ] ] [-e "command" ...]' print "Usage: "+sys.argv[0]+' [-c filename [-c filename2 ... ] ] [-e "command" ...]'
print " -c | --conf | --config - override startup .pronsolerc file" print " -c | --conf | --config - override startup .pronsolerc file"
print " may chain config files, settings auto-save will go into last file in the chain" print " may chain config files, settings auto-save will go into last file in the chain"
...@@ -1238,19 +1236,18 @@ class pronsole(cmd.Cmd): ...@@ -1238,19 +1236,18 @@ class pronsole(cmd.Cmd):
sys.exit() sys.exit()
if not self.rc_loaded: if not self.rc_loaded:
self.load_default_rc() self.load_default_rc()
for o,a in opts: for o, a in opts:
if o == "-e": if o == "-e":
self.processing_args = True self.processing_args = True
self.onecmd(a) self.onecmd(a)
self.processing_args = False self.processing_args = False
if __name__=="__main__": if __name__ == "__main__":
interp=pronsole() interp = pronsole()
interp.parse_cmdline(sys.argv[1:]) interp.parse_cmdline(sys.argv[1:])
try: try:
interp.cmdloop() interp.cmdloop()
except: except:
interp.p.disconnect() interp.p.disconnect()
#raise #raise
This source diff could not be displayed because it is too large. You can view the blob instead.
#!/usr/bin/env python #!/usr/bin/env python
# This file is part of the Printrun suite. # This file is part of the Printrun suite.
# #
# Printrun is free software: you can redistribute it and/or modify # Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Printrun is distributed in the hope that it will be useful, # Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>. # along with Printrun. If not, see <http://www.gnu.org/licenses/>.
...@@ -43,7 +43,7 @@ class install (_install): ...@@ -43,7 +43,7 @@ class install (_install):
except: except:
self.warn ("Could not write installed files list %s" % \ self.warn ("Could not write installed files list %s" % \
INSTALLED_FILES) INSTALLED_FILES)
return return
file.write (data) file.write (data)
file.close () file.close ()
...@@ -66,7 +66,7 @@ class uninstall (_install): ...@@ -66,7 +66,7 @@ class uninstall (_install):
except: except:
self.warn ("Could not read installed files list %s" % \ self.warn ("Could not read installed files list %s" % \
INSTALLED_FILES) INSTALLED_FILES)
return return
files = file.readlines () files = file.readlines ()
file.close () file.close ()
prepend = "" prepend = ""
...@@ -145,7 +145,7 @@ setup ( ...@@ -145,7 +145,7 @@ setup (
license = "GPLv3", license = "GPLv3",
data_files = data_files, data_files = data_files,
packages = ["printrun", "printrun.svg"], packages = ["printrun", "printrun.svg"],
scripts = ["pronsole.py", "pronterface.py", "plater.py"], scripts = ["pronsole.py", "pronterface.py", "plater.py", "printcore.py"],
cmdclass = {"uninstall" : uninstall, cmdclass = {"uninstall" : uninstall,
"install" : install, "install" : install,
"install_data" : install_data} "install_data" : install_data}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment