commit
093f6a4529
|
@ -1,2 +1,4 @@
|
|||
*.pyc
|
||||
.pronsolerc
|
||||
*.swp
|
||||
*.bak
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
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
README.i18n
10
README.i18n
|
@ -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
|
||||
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.
|
||||
|
||||
|
@ -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
|
||||
newlang="es" # use the correct code for your language
|
||||
mkdir -p locale/${newlang}/LC_MESSAGES
|
||||
cp locale/pronterface.pot locale/${newlanguage}/LC_MESSAGES/${newlang}.po
|
||||
cd locale/${newlanguage}/LC_MESSAGES/${newlang}
|
||||
cp locale/pronterface.pot locale/${newlanguage}/LC_MESSAGES/pronterface.po
|
||||
cd locale/${newlanguage}/LC_MESSAGES/
|
||||
# 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 :
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"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"
|
||||
"Last-Translator: Guillaume Seguin <guillaume@segu.in>\n"
|
||||
"Language-Team: FR <guillaume@segu.in>\n"
|
||||
|
@ -15,81 +15,81 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
|
||||
#: plater.py:247
|
||||
#: plater.py:246
|
||||
msgid "Plate building tool"
|
||||
msgstr "Outil d'assemblage de plateau"
|
||||
|
||||
#: plater.py:253
|
||||
#: plater.py:252
|
||||
msgid "Clear"
|
||||
msgstr "Vider"
|
||||
|
||||
#: plater.py:254
|
||||
#: plater.py:253
|
||||
msgid "Load"
|
||||
msgstr "Charger"
|
||||
|
||||
#: plater.py:256
|
||||
#: plater.py:255 plater.py:258
|
||||
msgid "Export"
|
||||
msgstr "Exporter"
|
||||
|
||||
#: plater.py:259
|
||||
#: plater.py:260
|
||||
msgid "Done"
|
||||
msgstr "Terminé"
|
||||
|
||||
#: plater.py:261
|
||||
#: plater.py:262
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#: plater.py:263
|
||||
#: plater.py:264
|
||||
msgid "Snap to Z = 0"
|
||||
msgstr "Poser en Z = 0"
|
||||
|
||||
#: plater.py:264
|
||||
#: plater.py:265
|
||||
msgid "Put at 100, 100"
|
||||
msgstr "Placer en 100, 100"
|
||||
|
||||
#: plater.py:265
|
||||
#: plater.py:266
|
||||
msgid "Delete"
|
||||
msgstr "Supprimer"
|
||||
|
||||
#: plater.py:266
|
||||
#: plater.py:267
|
||||
msgid "Auto"
|
||||
msgstr "Auto"
|
||||
|
||||
#: plater.py:290
|
||||
#: plater.py:291
|
||||
msgid "Autoplating"
|
||||
msgstr "Placement auto"
|
||||
|
||||
#: plater.py:318
|
||||
#: plater.py:319
|
||||
msgid "Bed full, sorry sir :("
|
||||
msgstr "Le lit est plein, désolé :("
|
||||
|
||||
#: plater.py:328
|
||||
#: plater.py:329
|
||||
msgid ""
|
||||
"Are you sure you want to clear the grid? All unsaved changes will be lost."
|
||||
msgstr ""
|
||||
"Êtes vous sur de vouloir vider la grille ? Toutes les modifications non "
|
||||
"enregistrées seront perdues."
|
||||
|
||||
#: plater.py:328
|
||||
#: plater.py:329
|
||||
msgid "Clear the grid?"
|
||||
msgstr "Vider la grille ?"
|
||||
|
||||
#: plater.py:370
|
||||
#: plater.py:371
|
||||
msgid "Pick file to save to"
|
||||
msgstr "Choisir le fichier dans lequel enregistrer"
|
||||
|
||||
#: plater.py:371
|
||||
#: plater.py:372
|
||||
msgid "STL files (;*.stl;*.STL;)"
|
||||
msgstr "Fichiers STL (;*.stl;*.STL;)"
|
||||
|
||||
#: plater.py:391
|
||||
#: plater.py:393
|
||||
msgid "wrote %s"
|
||||
msgstr "%s écrit"
|
||||
|
||||
#: plater.py:394
|
||||
#: plater.py:396
|
||||
msgid "Pick file to load"
|
||||
msgstr "Choisir le fichier à charger"
|
||||
|
||||
#: plater.py:395
|
||||
#: plater.py:397
|
||||
msgid "STL files (;*.stl;*.STL;)|*.stl|OpenSCAD files (;*.scad;)|*.scad"
|
||||
msgstr "Fichiers STL (;*.stl;*.STL;)|*.stl|Fichiers OpenSCAD (;*.scad;)|*.scad"
|
||||
|
|
Binary file not shown.
|
@ -5,7 +5,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"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"
|
||||
"Last-Translator: Guillaume Seguin <guillaume@segu.in>\n"
|
||||
"Language-Team: FR <c.laguilhon.debat@gmail.com>\n"
|
||||
|
@ -15,13 +15,49 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\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."
|
||||
msgstr ""
|
||||
"wxWidgets n'est pas installé. Ce programme nécessite la librairie wxWidgets "
|
||||
"pour fonctionner."
|
||||
|
||||
#: pronterface.py:81
|
||||
#: pronterface.py:93
|
||||
msgid ""
|
||||
"Dimensions of Build Platform\n"
|
||||
" & optional offset of origin\n"
|
||||
|
@ -32,55 +68,71 @@ msgid ""
|
|||
" XXXxYYYxZZZ+OffX+OffY+OffZ"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:82
|
||||
#: pronterface.py:94
|
||||
msgid "Last Set Temperature for the Heated Print Bed"
|
||||
msgstr "Dernière température du plateau chauffant définie"
|
||||
|
||||
#: pronterface.py:83
|
||||
#: pronterface.py:95
|
||||
msgid "Folder of last opened file"
|
||||
msgstr "Dossier du dernier fichier ouvert"
|
||||
|
||||
#: pronterface.py:84
|
||||
#: pronterface.py:96
|
||||
msgid "Last Temperature of the Hot End"
|
||||
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)"
|
||||
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)"
|
||||
msgstr "Espacement fin de la grille (défaut : 10)"
|
||||
|
||||
#: pronterface.py:87
|
||||
#: pronterface.py:99
|
||||
msgid "Coarse Grid Spacing (default: 50)"
|
||||
msgstr "Espacement large de la grille (défaut : 50)"
|
||||
|
||||
#: pronterface.py:88
|
||||
#: pronterface.py:100
|
||||
msgid "Pronterface background color (default: #FFFFFF)"
|
||||
msgstr "Couleur de fond de la Pronterface (défaut : #FFFFFF)"
|
||||
|
||||
#: pronterface.py:91
|
||||
#: pronterface.py:103
|
||||
msgid "Printer Interface"
|
||||
msgstr "Interface de l'imprimante"
|
||||
|
||||
#: pronterface.py:109
|
||||
#: pronterface.py:122
|
||||
msgid "Motors off"
|
||||
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"
|
||||
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"
|
||||
msgstr "Extruder"
|
||||
|
||||
#: pronterface.py:112
|
||||
#: pronterface.py:125
|
||||
msgid "Reverse"
|
||||
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 ""
|
||||
"# I moved all your custom buttons into .pronsolerc.\n"
|
||||
"# Please don't add them here any more.\n"
|
||||
|
@ -91,7 +143,7 @@ msgstr ""
|
|||
"# Veuillez ne plus en ajouter ici.\n"
|
||||
"# Une sauvegarde de vos anciens boutons est dans le fichier custombtn.old\n"
|
||||
|
||||
#: pronterface.py:135
|
||||
#: pronterface.py:148
|
||||
msgid ""
|
||||
"Note!!! You have specified custom buttons in both custombtn.txt and ."
|
||||
"pronsolerc"
|
||||
|
@ -99,36 +151,44 @@ msgstr ""
|
|||
"Remarque! Vous avez spécifié des boutons personnalisés dans custombtn.txt et "
|
||||
"aussi dans .pronsolerc"
|
||||
|
||||
#: pronterface.py:136
|
||||
#: pronterface.py:149
|
||||
msgid ""
|
||||
"Ignoring custombtn.txt. Remove all current buttons to revert to custombtn.txt"
|
||||
msgstr ""
|
||||
"custombtn.txt ignoré. Retirez tous les boutons en cours pour revenir à "
|
||||
"custombtn.txt"
|
||||
|
||||
#: pronterface.py:165 pronterface.py:520 pronterface.py:1343
|
||||
#: pronterface.py:1397 pronterface.py:1521 pronterface.py:1555
|
||||
#: pronterface.py:1567
|
||||
#: pronterface.py:181
|
||||
msgid "Failed to start web interface"
|
||||
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"
|
||||
msgstr "Imprimer"
|
||||
|
||||
#: pronterface.py:169
|
||||
#: pronterface.py:207
|
||||
msgid "Printer is now online."
|
||||
msgstr "L'imprimante est connectée"
|
||||
msgstr "Imprimante connectée."
|
||||
|
||||
#: pronterface.py:170
|
||||
#: pronterface.py:208
|
||||
msgid "Disconnect"
|
||||
msgstr "Déconnecter"
|
||||
|
||||
#: pronterface.py:229
|
||||
#: pronterface.py:331
|
||||
msgid "Setting hotend temperature to %f degrees 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."
|
||||
msgstr "L'imprimante est déconnectée"
|
||||
msgstr "Imprimante déconnectée."
|
||||
|
||||
#: pronterface.py:250
|
||||
#: pronterface.py:336
|
||||
msgid ""
|
||||
"You cannot set negative temperatures. To turn the hotend off entirely, set "
|
||||
"its temperature to 0."
|
||||
|
@ -136,15 +196,15 @@ msgstr ""
|
|||
"Vous ne pouvez pas régler une température négative. Pour éteindre la buse, "
|
||||
"réglez sa température à 0°C."
|
||||
|
||||
#: pronterface.py:252
|
||||
#: pronterface.py:338 pronterface.py:364
|
||||
msgid "You must enter a temperature. (%s)"
|
||||
msgstr "Vous devez saisir une température. (%s)"
|
||||
|
||||
#: pronterface.py:265
|
||||
#: pronterface.py:353
|
||||
msgid "Setting bed temperature to %f degrees Celsius."
|
||||
msgstr "Réglage de la température du plateau à %f degrés Celsius."
|
||||
|
||||
#: pronterface.py:286
|
||||
#: pronterface.py:360
|
||||
msgid ""
|
||||
"You cannot set negative temperatures. To turn the bed off entirely, set its "
|
||||
"temperature to 0."
|
||||
|
@ -152,343 +212,328 @@ msgstr ""
|
|||
"Vous ne pouvez pas régler une température négative. Pour désactiver votre "
|
||||
"plateau chauffant, réglez sa température à 0°C."
|
||||
|
||||
#: pronterface.py:288
|
||||
msgid "You must enter a temperature."
|
||||
msgstr "Vous devez saisir une température."
|
||||
|
||||
#: pronterface.py:303
|
||||
#: pronterface.py:381
|
||||
msgid "Do you want to erase the macro?"
|
||||
msgstr "Voulez-vous effacer la macro ?"
|
||||
|
||||
#: pronterface.py:307
|
||||
#: pronterface.py:385
|
||||
msgid "Cancelled."
|
||||
msgstr "Annulé"
|
||||
|
||||
#: pronterface.py:352
|
||||
#: pronterface.py:436
|
||||
msgid " Opens file"
|
||||
msgstr " Ouvrir un fichier"
|
||||
|
||||
#: pronterface.py:352
|
||||
#: pronterface.py:436
|
||||
msgid "&Open..."
|
||||
msgstr "&Ouvrir..."
|
||||
|
||||
#: pronterface.py:353
|
||||
#: pronterface.py:437
|
||||
msgid " Edit open file"
|
||||
msgstr " Éditer le fichier ouvert"
|
||||
|
||||
#: pronterface.py:353
|
||||
#: pronterface.py:437
|
||||
msgid "&Edit..."
|
||||
msgstr "&Éditer..."
|
||||
|
||||
#: pronterface.py:354
|
||||
#: pronterface.py:438
|
||||
msgid " Clear output console"
|
||||
msgstr " Effacer le contenu de la console de sortie"
|
||||
|
||||
#: pronterface.py:354
|
||||
#: pronterface.py:438
|
||||
msgid "Clear console"
|
||||
msgstr "Effacer la console"
|
||||
|
||||
#: pronterface.py:355
|
||||
#: pronterface.py:439
|
||||
msgid " Project slices"
|
||||
msgstr " Projeter les couches"
|
||||
|
||||
#: pronterface.py:355
|
||||
#: pronterface.py:439
|
||||
msgid "Projector"
|
||||
msgstr "Projecteur"
|
||||
|
||||
#: pronterface.py:356
|
||||
#: pronterface.py:440
|
||||
msgid " Closes the Window"
|
||||
msgstr " Quitter le programme"
|
||||
|
||||
#: pronterface.py:356
|
||||
#: pronterface.py:440
|
||||
msgid "E&xit"
|
||||
msgstr "&Quitter"
|
||||
|
||||
#: pronterface.py:357
|
||||
#: pronterface.py:441
|
||||
msgid "&File"
|
||||
msgstr "&Fichier"
|
||||
|
||||
#: pronterface.py:362
|
||||
#: pronterface.py:446
|
||||
msgid "&Macros"
|
||||
msgstr "&Macros"
|
||||
|
||||
#: pronterface.py:363
|
||||
#: pronterface.py:447
|
||||
msgid "<&New...>"
|
||||
msgstr "<&Nouvelle...>"
|
||||
|
||||
#: pronterface.py:364
|
||||
#: pronterface.py:448
|
||||
msgid " Options dialog"
|
||||
msgstr " Fenêtre des options"
|
||||
|
||||
#: pronterface.py:364
|
||||
#: pronterface.py:448
|
||||
msgid "&Options"
|
||||
msgstr "&Options"
|
||||
|
||||
#: pronterface.py:366
|
||||
#: pronterface.py:450
|
||||
msgid " Adjust slicing settings"
|
||||
msgstr " Régler les paramètres de slicing"
|
||||
|
||||
#: pronterface.py:366
|
||||
#: pronterface.py:450
|
||||
msgid "Slicing Settings"
|
||||
msgstr "Paramètres de slicing"
|
||||
|
||||
#: pronterface.py:373
|
||||
#: pronterface.py:452
|
||||
msgid "&Settings"
|
||||
msgstr "&Paramètres"
|
||||
|
||||
#: pronterface.py:389
|
||||
#: pronterface.py:467
|
||||
msgid "Enter macro name"
|
||||
msgstr "Saisissez le nom de la macro"
|
||||
|
||||
#: pronterface.py:392
|
||||
#: pronterface.py:470
|
||||
msgid "Macro name:"
|
||||
msgstr "Nom :"
|
||||
|
||||
#: pronterface.py:395
|
||||
#: pronterface.py:473
|
||||
msgid "Ok"
|
||||
msgstr "Valider"
|
||||
|
||||
#: pronterface.py:399 pronterface.py:1354 pronterface.py:1613
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
#: pronterface.py:495
|
||||
msgid "Macro name may contain only ASCII alphanumeric symbols and underscores"
|
||||
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"
|
||||
msgstr "Le nom '%s' est utilisé par une commande interne"
|
||||
|
||||
#: pronterface.py:420
|
||||
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
|
||||
#: pronterface.py:548
|
||||
msgid "Port"
|
||||
msgstr "Port"
|
||||
|
||||
#: pronterface.py:488
|
||||
#: pronterface.py:570 pronterface.py:1747
|
||||
msgid "Connect"
|
||||
msgstr "Connecter"
|
||||
|
||||
#: pronterface.py:490
|
||||
msgid "Connect to the printer"
|
||||
msgstr "Connecter l'imprimante"
|
||||
|
||||
#: pronterface.py:492
|
||||
#: pronterface.py:574
|
||||
msgid "Reset"
|
||||
msgstr "Réinitialiser"
|
||||
|
||||
#: pronterface.py:495 pronterface.py:772
|
||||
msgid "Mini mode"
|
||||
msgstr "Mode réduit"
|
||||
|
||||
#: pronterface.py:499
|
||||
msgid "Monitor Printer"
|
||||
msgstr "Surveiller l'imprimante"
|
||||
|
||||
#: pronterface.py:509
|
||||
#: pronterface.py:589
|
||||
msgid "Load file"
|
||||
msgstr "Charger un fichier"
|
||||
|
||||
#: pronterface.py:512
|
||||
#: pronterface.py:593
|
||||
msgid "Compose"
|
||||
msgstr "Composer"
|
||||
|
||||
#: pronterface.py:516
|
||||
#: pronterface.py:598
|
||||
msgid "SD"
|
||||
msgstr "SD"
|
||||
|
||||
#: pronterface.py:524 pronterface.py:1398 pronterface.py:1444
|
||||
#: pronterface.py:1495 pronterface.py:1520 pronterface.py:1554
|
||||
#: pronterface.py:1570
|
||||
#: pronterface.py:608 pronterface.py:1579 pronterface.py:1631
|
||||
#: pronterface.py:1681 pronterface.py:1704 pronterface.py:1764
|
||||
#: pronterface.py:1781
|
||||
msgid "Pause"
|
||||
msgstr "Pause"
|
||||
|
||||
#: pronterface.py:537
|
||||
#: pronterface.py:612
|
||||
msgid "Recover"
|
||||
msgstr "Récupérer"
|
||||
|
||||
#: pronterface.py:630
|
||||
msgid "Send"
|
||||
msgstr "Envoyer"
|
||||
|
||||
#: pronterface.py:545 pronterface.py:646
|
||||
msgid "mm/min"
|
||||
msgstr "mm/min"
|
||||
|
||||
#: pronterface.py:547
|
||||
#: pronterface.py:671
|
||||
msgid "XY:"
|
||||
msgstr "XY:"
|
||||
|
||||
#: pronterface.py:549
|
||||
msgid "Z:"
|
||||
msgstr "Z:"
|
||||
#: pronterface.py:673
|
||||
msgid "mm/min Z:"
|
||||
msgstr "mm/min Z:"
|
||||
|
||||
#: pronterface.py:572 pronterface.py:653
|
||||
msgid "Heater:"
|
||||
msgstr "Buse :"
|
||||
#: pronterface.py:678
|
||||
msgid "Watch"
|
||||
msgstr "Surveiller"
|
||||
|
||||
#: pronterface.py:575 pronterface.py:595
|
||||
#: pronterface.py:683
|
||||
msgid "Heat:"
|
||||
msgstr "Buse:"
|
||||
|
||||
#: pronterface.py:686 pronterface.py:709
|
||||
msgid "Off"
|
||||
msgstr "Off"
|
||||
|
||||
#: pronterface.py:587 pronterface.py:607
|
||||
#: pronterface.py:700 pronterface.py:723
|
||||
msgid "Set"
|
||||
msgstr "Régler"
|
||||
|
||||
#: pronterface.py:592 pronterface.py:655
|
||||
#: pronterface.py:706
|
||||
msgid "Bed:"
|
||||
msgstr "Plateau :"
|
||||
|
||||
#: pronterface.py:640
|
||||
#: pronterface.py:756
|
||||
msgid "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."
|
||||
msgstr "Imprimante non connectée."
|
||||
|
||||
#: pronterface.py:727
|
||||
#: pronterface.py:869
|
||||
msgid "SD Upload"
|
||||
msgstr "Copier sur SD"
|
||||
|
||||
#: pronterface.py:731
|
||||
#: pronterface.py:873
|
||||
msgid "SD Print"
|
||||
msgstr "Imprimer depuis SD"
|
||||
|
||||
#: pronterface.py:779
|
||||
#: pronterface.py:914
|
||||
msgid "Mini mode"
|
||||
msgstr "Mode réduit"
|
||||
|
||||
#: pronterface.py:921
|
||||
msgid "Full mode"
|
||||
msgstr "Mode complet"
|
||||
|
||||
#: pronterface.py:804
|
||||
#: pronterface.py:946
|
||||
msgid "Execute command: "
|
||||
msgstr "Exécuter la commande :"
|
||||
|
||||
#: pronterface.py:815
|
||||
#: pronterface.py:957
|
||||
msgid "click to add new custom button"
|
||||
msgstr "Ajouter un bouton personnalisé"
|
||||
|
||||
#: pronterface.py:834
|
||||
#: pronterface.py:979
|
||||
msgid ""
|
||||
"Defines custom button. Usage: button <num> \"title\" [/c \"colour\"] command"
|
||||
msgstr ""
|
||||
"Définit des boutons personnalidés. Utilisation : <numero> \"Libelle\" [/c "
|
||||
"\"couleur\"] commande"
|
||||
|
||||
#: pronterface.py:856
|
||||
#: pronterface.py:1003
|
||||
msgid "Custom button number should be between 0 and 63"
|
||||
msgstr ""
|
||||
"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'"
|
||||
msgstr "Editer le bouton personnalisé '%s'"
|
||||
|
||||
#: pronterface.py:950
|
||||
#: pronterface.py:1098
|
||||
msgid "Move left <<"
|
||||
msgstr "Déplacer vers la gauche <<"
|
||||
|
||||
#: pronterface.py:953
|
||||
#: pronterface.py:1101
|
||||
msgid "Move right >>"
|
||||
msgstr "Déplacer vers la droite >>"
|
||||
|
||||
#: pronterface.py:957
|
||||
#: pronterface.py:1105
|
||||
msgid "Remove custom button '%s'"
|
||||
msgstr "Supprimer le bouton personnalisé '%s'"
|
||||
|
||||
#: pronterface.py:960
|
||||
#: pronterface.py:1108
|
||||
msgid "Add custom button"
|
||||
msgstr "Ajouter un bouton personnalisé"
|
||||
|
||||
#: pronterface.py:1105
|
||||
#: pronterface.py:1270
|
||||
msgid "event object missing"
|
||||
msgstr "événement d'objet manquant"
|
||||
|
||||
#: pronterface.py:1133
|
||||
#: pronterface.py:1306
|
||||
msgid "Invalid period given."
|
||||
msgstr "La période donnée est invalide"
|
||||
|
||||
#: pronterface.py:1136
|
||||
#: pronterface.py:1311
|
||||
msgid "Monitoring printer."
|
||||
msgstr "Imprimante sous surveillance."
|
||||
|
||||
#: pronterface.py:1138
|
||||
#: pronterface.py:1315
|
||||
msgid "Done monitoring."
|
||||
msgstr "Surveillance de l'imprimante effectuée."
|
||||
|
||||
#: pronterface.py:1160
|
||||
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
|
||||
#: pronterface.py:1355
|
||||
msgid " SD printing:%04.2f %%"
|
||||
msgstr " Impression SD : %04.2f %%"
|
||||
|
||||
#: pronterface.py:1178
|
||||
msgid " Printing:%04.2f %% |"
|
||||
msgstr " Impression : %04.2f %% |"
|
||||
#: pronterface.py:1358
|
||||
msgid " Printing: %04.2f%% |"
|
||||
msgstr " Impression : %04.2f%% |"
|
||||
|
||||
#: pronterface.py:1179
|
||||
#: pronterface.py:1359
|
||||
msgid " Line# %d of %d lines |"
|
||||
msgstr " Ligne# %d sur %d lignes |"
|
||||
|
||||
#: pronterface.py:1184
|
||||
#: pronterface.py:1364
|
||||
msgid " Est: %s of %s remaining | "
|
||||
msgstr " ETA: %s restant sur %s | "
|
||||
|
||||
#: pronterface.py:1186
|
||||
#: pronterface.py:1366
|
||||
msgid " Z: %0.2f mm"
|
||||
msgstr " Z: %0.2f mm"
|
||||
|
||||
#: pronterface.py:1257
|
||||
#: pronterface.py:1439
|
||||
msgid "Opening file failed."
|
||||
msgstr "L'ouverture du fichier a échoué"
|
||||
|
||||
#: pronterface.py:1263
|
||||
#: pronterface.py:1445
|
||||
msgid "Starting print"
|
||||
msgstr "Début de l'impression..."
|
||||
|
||||
#: pronterface.py:1286
|
||||
#: pronterface.py:1466
|
||||
msgid "Pick SD file"
|
||||
msgstr "Choisir un fichier sur la carte SD"
|
||||
|
||||
#: pronterface.py:1286
|
||||
#: pronterface.py:1466
|
||||
msgid "Select the file to print"
|
||||
msgstr "Sélectionnez le fichier à imprimer :"
|
||||
|
||||
#: pronterface.py:1321
|
||||
#: pronterface.py:1501
|
||||
msgid "Failed to execute slicing software: "
|
||||
msgstr "Une erreur s'est produite lors du slicing : "
|
||||
|
||||
#: pronterface.py:1328
|
||||
#: pronterface.py:1510
|
||||
msgid "Slicing..."
|
||||
msgstr "Slicing..."
|
||||
|
||||
#: pronterface.py:1341
|
||||
#: pronterface.py:1523
|
||||
msgid ", %d lines"
|
||||
msgstr ", %d lignes"
|
||||
|
||||
#: pronterface.py:1348
|
||||
#: pronterface.py:1523
|
||||
msgid "Loaded "
|
||||
msgstr "Chargé "
|
||||
|
||||
#: pronterface.py:1530
|
||||
msgid "Load File"
|
||||
msgstr "Charger un fichier"
|
||||
|
||||
#: pronterface.py:1355
|
||||
#: pronterface.py:1536
|
||||
msgid "Slicing "
|
||||
msgstr "Slicing "
|
||||
|
||||
#: pronterface.py:1374
|
||||
#: pronterface.py:1555
|
||||
msgid "Open file to print"
|
||||
msgstr "Ouvrir un fichier à imprimer"
|
||||
|
||||
#: 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 (*.*)|*.*"
|
||||
|
@ -496,114 +541,86 @@ msgstr ""
|
|||
"Fichiers OBJ, STL et GCODE (;*.gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ;)|*."
|
||||
"gcode;*.gco;*.g;*.stl;*.STL;*.obj;*.OBJ|Tous les fichiers (*.*)|*.*"
|
||||
|
||||
#: pronterface.py:1382
|
||||
#: pronterface.py:1563
|
||||
msgid "File not found!"
|
||||
msgstr "Fichier non trouvé"
|
||||
|
||||
#: pronterface.py:1396
|
||||
#: pronterface.py:1577
|
||||
msgid "Loaded %s, %d lines"
|
||||
msgstr "%s chargé, %d lignes"
|
||||
|
||||
#: pronterface.py:1406
|
||||
#: pronterface.py:1588
|
||||
msgid "mm of filament used in this print\n"
|
||||
msgstr "mm de filament utilisés pour cette impression\n"
|
||||
|
||||
#: pronterface.py:1407
|
||||
#: pronterface.py:1589 pronterface.py:1591
|
||||
msgid ""
|
||||
"the print goes from %f mm to %f mm in X\n"
|
||||
"and is %f mm wide\n"
|
||||
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"
|
||||
|
||||
#: pronterface.py:1408
|
||||
#: pronterface.py:1592
|
||||
msgid ""
|
||||
"the print goes from %f mm to %f mm in Y\n"
|
||||
"and is %f mm wide\n"
|
||||
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"
|
||||
|
||||
#: pronterface.py:1409
|
||||
#: pronterface.py:1593
|
||||
msgid ""
|
||||
"the print goes from %f mm to %f mm in Z\n"
|
||||
"and is %f mm high\n"
|
||||
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"
|
||||
|
||||
#: pronterface.py:1410
|
||||
#: pronterface.py:1595
|
||||
msgid "Estimated duration (pessimistic): "
|
||||
msgstr "Durée estimée (pessimiste) : "
|
||||
|
||||
#: pronterface.py:1435
|
||||
#: pronterface.py:1622
|
||||
msgid "No file loaded. Please use load first."
|
||||
msgstr "Aucun fichier chargé. Veuillez charger un fichier avant."
|
||||
|
||||
#: pronterface.py:1446
|
||||
#: pronterface.py:1633
|
||||
msgid "Restart"
|
||||
msgstr "Recommencer"
|
||||
|
||||
#: pronterface.py:1450
|
||||
#: pronterface.py:1637
|
||||
msgid "File upload complete"
|
||||
msgstr "Envoi du fichier terminé"
|
||||
|
||||
#: pronterface.py:1469
|
||||
#: pronterface.py:1656
|
||||
msgid "Pick SD filename"
|
||||
msgstr "Lister les fichiers sur la carte SD"
|
||||
|
||||
#: pronterface.py:1477
|
||||
#: pronterface.py:1663
|
||||
msgid "Paused."
|
||||
msgstr "En pause."
|
||||
|
||||
#: pronterface.py:1488
|
||||
#: pronterface.py:1674
|
||||
msgid "Resume"
|
||||
msgstr "Reprendre"
|
||||
|
||||
#: pronterface.py:1504
|
||||
#: pronterface.py:1688
|
||||
msgid "Connecting..."
|
||||
msgstr "Connection en cours..."
|
||||
msgstr "Connexion en cours..."
|
||||
|
||||
#: pronterface.py:1535
|
||||
#: pronterface.py:1738
|
||||
msgid "Disconnected."
|
||||
msgstr "Déconnecté."
|
||||
|
||||
#: pronterface.py:1562
|
||||
#: pronterface.py:1771
|
||||
msgid "Reset."
|
||||
msgstr "Réinitialisée."
|
||||
|
||||
#: pronterface.py:1563
|
||||
#: pronterface.py:1772
|
||||
msgid "Are you sure you want to reset the printer?"
|
||||
msgstr "Etes-vous sûr de vouloir réinitialiser l'imprimante?"
|
||||
|
||||
#: pronterface.py:1563
|
||||
#: pronterface.py:1772
|
||||
msgid "Reset?"
|
||||
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 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"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"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -15,79 +15,79 @@ msgstr ""
|
|||
"Generated-By: pygettext.py 1.5\n"
|
||||
|
||||
|
||||
#: plater.py:247
|
||||
#: plater.py:246
|
||||
msgid "Plate building tool"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:253
|
||||
#: plater.py:252
|
||||
msgid "Clear"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:254
|
||||
#: plater.py:253
|
||||
msgid "Load"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:256
|
||||
#: plater.py:255 plater.py:258
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:259
|
||||
#: plater.py:260
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:261
|
||||
#: plater.py:262
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:263
|
||||
#: plater.py:264
|
||||
msgid "Snap to Z = 0"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:264
|
||||
#: plater.py:265
|
||||
msgid "Put at 100, 100"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:265
|
||||
#: plater.py:266
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:266
|
||||
#: plater.py:267
|
||||
msgid "Auto"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:290
|
||||
#: plater.py:291
|
||||
msgid "Autoplating"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:318
|
||||
#: plater.py:319
|
||||
msgid "Bed full, sorry sir :("
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:328
|
||||
#: plater.py:329
|
||||
msgid "Are you sure you want to clear the grid? All unsaved changes will be lost."
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:328
|
||||
#: plater.py:329
|
||||
msgid "Clear the grid?"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:370
|
||||
#: plater.py:371
|
||||
msgid "Pick file to save to"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:371
|
||||
#: plater.py:372
|
||||
msgid "STL files (;*.stl;*.STL;)"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:391
|
||||
#: plater.py:393
|
||||
msgid "wrote %s"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:394
|
||||
#: plater.py:396
|
||||
msgid "Pick file to load"
|
||||
msgstr ""
|
||||
|
||||
#: plater.py:395
|
||||
#: plater.py:397
|
||||
msgid "STL files (;*.stl;*.STL;)|*.stl|OpenSCAD files (;*.scad;)|*.scad"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"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"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -15,11 +15,47 @@ msgstr ""
|
|||
"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."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:81
|
||||
#: pronterface.py:93
|
||||
msgid ""
|
||||
"Dimensions of Build Platform\n"
|
||||
" & optional offset of origin\n"
|
||||
|
@ -30,545 +66,524 @@ msgid ""
|
|||
" XXXxYYYxZZZ+OffX+OffY+OffZ"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:82
|
||||
#: pronterface.py:94
|
||||
msgid "Last Set Temperature for the Heated Print Bed"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:83
|
||||
#: pronterface.py:95
|
||||
msgid "Folder of last opened file"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:84
|
||||
#: pronterface.py:96
|
||||
msgid "Last Temperature of the Hot End"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:85
|
||||
#: pronterface.py:97
|
||||
msgid "Width of Extrusion in Preview (default: 0.5)"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:86
|
||||
#: pronterface.py:98
|
||||
msgid "Fine Grid Spacing (default: 10)"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:87
|
||||
#: pronterface.py:99
|
||||
msgid "Coarse Grid Spacing (default: 50)"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:88
|
||||
#: pronterface.py:100
|
||||
msgid "Pronterface background color (default: #FFFFFF)"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:91
|
||||
#: pronterface.py:103
|
||||
msgid "Printer Interface"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:109
|
||||
#: pronterface.py:122
|
||||
msgid "Motors off"
|
||||
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"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:111
|
||||
#: pronterface.py:124
|
||||
msgid "Advance extruder by set length"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:124
|
||||
msgid "Extrude"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:112
|
||||
#: pronterface.py:125
|
||||
msgid "Reverse"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:130
|
||||
#: pronterface.py:125
|
||||
msgid "Reverse extruder by set length"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:143
|
||||
msgid ""
|
||||
"# I moved all your custom buttons into .pronsolerc.\n"
|
||||
"# Please don't add them here any more.\n"
|
||||
"# Backup of your old buttons is in custombtn.old\n"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:135
|
||||
#: pronterface.py:148
|
||||
msgid "Note!!! You have specified custom buttons in both custombtn.txt and .pronsolerc"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:136
|
||||
#: pronterface.py:149
|
||||
msgid "Ignoring custombtn.txt. Remove all current buttons to revert to custombtn.txt"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:165 pronterface.py:520 pronterface.py:1343
|
||||
#: pronterface.py:1397 pronterface.py:1521 pronterface.py:1555
|
||||
#: pronterface.py:1567
|
||||
#: pronterface.py:181
|
||||
msgid "Failed to start web interface"
|
||||
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"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:169
|
||||
#: pronterface.py:207
|
||||
msgid "Printer is now online."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:170
|
||||
#: pronterface.py:208
|
||||
msgid "Disconnect"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:229
|
||||
#: pronterface.py:331
|
||||
msgid "Setting hotend temperature to %f degrees Celsius."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:248 pronterface.py:284 pronterface.py:346
|
||||
#: pronterface.py:334 pronterface.py:356 pronterface.py:428
|
||||
msgid "Printer is not online."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:250
|
||||
#: pronterface.py:336
|
||||
msgid "You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:252
|
||||
#: pronterface.py:338 pronterface.py:364
|
||||
msgid "You must enter a temperature. (%s)"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:265
|
||||
#: pronterface.py:353
|
||||
msgid "Setting bed temperature to %f degrees Celsius."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:286
|
||||
#: pronterface.py:360
|
||||
msgid "You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:288
|
||||
msgid "You must enter a temperature."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:303
|
||||
#: pronterface.py:381
|
||||
msgid "Do you want to erase the macro?"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:307
|
||||
#: pronterface.py:385
|
||||
msgid "Cancelled."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:352
|
||||
#: pronterface.py:436
|
||||
msgid " Opens file"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:352
|
||||
#: pronterface.py:436
|
||||
msgid "&Open..."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:353
|
||||
#: pronterface.py:437
|
||||
msgid " Edit open file"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:353
|
||||
#: pronterface.py:437
|
||||
msgid "&Edit..."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:354
|
||||
#: pronterface.py:438
|
||||
msgid " Clear output console"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:354
|
||||
#: pronterface.py:438
|
||||
msgid "Clear console"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:355
|
||||
#: pronterface.py:439
|
||||
msgid " Project slices"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:355
|
||||
#: pronterface.py:439
|
||||
msgid "Projector"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:356
|
||||
#: pronterface.py:440
|
||||
msgid " Closes the Window"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:356
|
||||
#: pronterface.py:440
|
||||
msgid "E&xit"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:357
|
||||
#: pronterface.py:441
|
||||
msgid "&File"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:362
|
||||
#: pronterface.py:446
|
||||
msgid "&Macros"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:363
|
||||
#: pronterface.py:447
|
||||
msgid "<&New...>"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:364
|
||||
#: pronterface.py:448
|
||||
msgid " Options dialog"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:364
|
||||
#: pronterface.py:448
|
||||
msgid "&Options"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:366
|
||||
#: pronterface.py:450
|
||||
msgid " Adjust slicing settings"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:366
|
||||
#: pronterface.py:450
|
||||
msgid "Slicing Settings"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:373
|
||||
#: pronterface.py:452
|
||||
msgid "&Settings"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:389
|
||||
#: pronterface.py:467
|
||||
msgid "Enter macro name"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:392
|
||||
#: pronterface.py:470
|
||||
msgid "Macro name:"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:395
|
||||
#: pronterface.py:473
|
||||
msgid "Ok"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:399 pronterface.py:1354 pronterface.py:1613
|
||||
msgid "Cancel"
|
||||
#: pronterface.py:495
|
||||
msgid "Macro name may contain only ASCII alphanumeric symbols and underscores"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:417
|
||||
#: pronterface.py:500
|
||||
msgid "Name '%s' is being used by built-in command"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:420
|
||||
msgid "Macro name may contain only alphanumeric symbols and underscores"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:469
|
||||
#: pronterface.py:548
|
||||
msgid "Port"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:488
|
||||
#: pronterface.py:570 pronterface.py:1747
|
||||
msgid "Connect"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:490
|
||||
msgid "Connect to the printer"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:492
|
||||
#: pronterface.py:574
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:495 pronterface.py:772
|
||||
msgid "Mini mode"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:499
|
||||
msgid "Monitor Printer"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:509
|
||||
#: pronterface.py:589
|
||||
msgid "Load file"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:512
|
||||
#: pronterface.py:593
|
||||
msgid "Compose"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:516
|
||||
#: pronterface.py:598
|
||||
msgid "SD"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:524 pronterface.py:1398 pronterface.py:1444
|
||||
#: pronterface.py:1495 pronterface.py:1520 pronterface.py:1554
|
||||
#: pronterface.py:1570
|
||||
#: pronterface.py:608 pronterface.py:1579 pronterface.py:1631
|
||||
#: pronterface.py:1681 pronterface.py:1704 pronterface.py:1764
|
||||
#: pronterface.py:1781
|
||||
msgid "Pause"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:537
|
||||
#: pronterface.py:612
|
||||
msgid "Recover"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:630
|
||||
msgid "Send"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:545 pronterface.py:646
|
||||
msgid "mm/min"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:547
|
||||
#: pronterface.py:671
|
||||
msgid "XY:"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:549
|
||||
msgid "Z:"
|
||||
#: pronterface.py:673
|
||||
msgid "mm/min Z:"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:572 pronterface.py:653
|
||||
msgid "Heater:"
|
||||
#: pronterface.py:678
|
||||
msgid "Watch"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:575 pronterface.py:595
|
||||
#: pronterface.py:683
|
||||
msgid "Heat:"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:686 pronterface.py:709
|
||||
msgid "Off"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:587 pronterface.py:607
|
||||
#: pronterface.py:700 pronterface.py:723
|
||||
msgid "Set"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:592 pronterface.py:655
|
||||
#: pronterface.py:706
|
||||
msgid "Bed:"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:640
|
||||
#: pronterface.py:756
|
||||
msgid "mm"
|
||||
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."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:727
|
||||
#: pronterface.py:869
|
||||
msgid "SD Upload"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:731
|
||||
#: pronterface.py:873
|
||||
msgid "SD Print"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:779
|
||||
#: pronterface.py:914
|
||||
msgid "Mini mode"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:921
|
||||
msgid "Full mode"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:804
|
||||
#: pronterface.py:946
|
||||
msgid "Execute command: "
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:815
|
||||
#: pronterface.py:957
|
||||
msgid "click to add new custom button"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:834
|
||||
#: pronterface.py:979
|
||||
msgid "Defines custom button. Usage: button <num> \"title\" [/c \"colour\"] command"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:856
|
||||
#: pronterface.py:1003
|
||||
msgid "Custom button number should be between 0 and 63"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:948
|
||||
#: pronterface.py:1096
|
||||
msgid "Edit custom button '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:950
|
||||
#: pronterface.py:1098
|
||||
msgid "Move left <<"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:953
|
||||
#: pronterface.py:1101
|
||||
msgid "Move right >>"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:957
|
||||
#: pronterface.py:1105
|
||||
msgid "Remove custom button '%s'"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:960
|
||||
#: pronterface.py:1108
|
||||
msgid "Add custom button"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1105
|
||||
#: pronterface.py:1270
|
||||
msgid "event object missing"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1133
|
||||
#: pronterface.py:1306
|
||||
msgid "Invalid period given."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1136
|
||||
#: pronterface.py:1311
|
||||
msgid "Monitoring printer."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1138
|
||||
#: pronterface.py:1315
|
||||
msgid "Done monitoring."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1160
|
||||
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
|
||||
#: pronterface.py:1355
|
||||
msgid " SD printing:%04.2f %%"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1178
|
||||
msgid " Printing:%04.2f %% |"
|
||||
#: pronterface.py:1358
|
||||
msgid " Printing: %04.2f%% |"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1179
|
||||
#: pronterface.py:1359
|
||||
msgid " Line# %d of %d lines |"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1184
|
||||
#: pronterface.py:1364
|
||||
msgid " Est: %s of %s remaining | "
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1186
|
||||
#: pronterface.py:1366
|
||||
msgid " Z: %0.2f mm"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1257
|
||||
#: pronterface.py:1439
|
||||
msgid "Opening file failed."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1263
|
||||
#: pronterface.py:1445
|
||||
msgid "Starting print"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1286
|
||||
#: pronterface.py:1466
|
||||
msgid "Pick SD file"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1286
|
||||
#: pronterface.py:1466
|
||||
msgid "Select the file to print"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1321
|
||||
#: pronterface.py:1501
|
||||
msgid "Failed to execute slicing software: "
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1328
|
||||
#: pronterface.py:1510
|
||||
msgid "Slicing..."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1341
|
||||
#: pronterface.py:1523
|
||||
msgid ", %d lines"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1348
|
||||
#: pronterface.py:1523
|
||||
msgid "Loaded "
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1530
|
||||
msgid "Load File"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1355
|
||||
#: pronterface.py:1536
|
||||
msgid "Slicing "
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1374
|
||||
#: pronterface.py:1555
|
||||
msgid "Open file to print"
|
||||
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 (*.*)|*.*"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1382
|
||||
#: pronterface.py:1563
|
||||
msgid "File not found!"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1396
|
||||
#: pronterface.py:1577
|
||||
msgid "Loaded %s, %d lines"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1406
|
||||
#: pronterface.py:1588
|
||||
msgid ""
|
||||
"mm of filament used in this print\n"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1407
|
||||
#: pronterface.py:1589 pronterface.py:1591
|
||||
msgid ""
|
||||
"the print goes from %f mm to %f mm in X\n"
|
||||
"and is %f mm wide\n"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1408
|
||||
#: pronterface.py:1592
|
||||
msgid ""
|
||||
"the print goes from %f mm to %f mm in Y\n"
|
||||
"and is %f mm wide\n"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1409
|
||||
#: pronterface.py:1593
|
||||
msgid ""
|
||||
"the print goes from %f mm to %f mm in Z\n"
|
||||
"and is %f mm high\n"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1410
|
||||
#: pronterface.py:1595
|
||||
msgid "Estimated duration (pessimistic): "
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1435
|
||||
#: pronterface.py:1622
|
||||
msgid "No file loaded. Please use load first."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1446
|
||||
#: pronterface.py:1633
|
||||
msgid "Restart"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1450
|
||||
#: pronterface.py:1637
|
||||
msgid "File upload complete"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1469
|
||||
#: pronterface.py:1656
|
||||
msgid "Pick SD filename"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1477
|
||||
#: pronterface.py:1663
|
||||
msgid "Paused."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1488
|
||||
#: pronterface.py:1674
|
||||
msgid "Resume"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1504
|
||||
#: pronterface.py:1688
|
||||
msgid "Connecting..."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1535
|
||||
#: pronterface.py:1738
|
||||
msgid "Disconnected."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1562
|
||||
#: pronterface.py:1771
|
||||
msgid "Reset."
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1563
|
||||
#: pronterface.py:1772
|
||||
msgid "Are you sure you want to reset the printer?"
|
||||
msgstr ""
|
||||
|
||||
#: pronterface.py:1563
|
||||
#: pronterface.py:1772
|
||||
msgid "Reset?"
|
||||
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 ""
|
||||
|
||||
|
|
74
plater.py
74
plater.py
|
@ -1,17 +1,17 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# 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/>.
|
||||
|
||||
|
@ -46,7 +46,7 @@ def evalme(s):
|
|||
|
||||
|
||||
class stlwrap:
|
||||
def __init__(self, obj, name=None):
|
||||
def __init__(self, obj, name = None):
|
||||
self.obj = obj
|
||||
self.name = name
|
||||
if name is None:
|
||||
|
@ -58,7 +58,7 @@ class stlwrap:
|
|||
|
||||
class showstl(wx.Window):
|
||||
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))
|
||||
#wx.FutureCall(200, self.paint)
|
||||
self.i = 0
|
||||
|
@ -141,7 +141,7 @@ class showstl(wx.Window):
|
|||
self.i += angle
|
||||
if not self.triggered:
|
||||
self.triggered = 1
|
||||
threading.Thread(target=self.cr).start()
|
||||
threading.Thread(target = self.cr).start()
|
||||
|
||||
def keypress(self, event):
|
||||
"""gets keypress events and moves/rotates acive shape"""
|
||||
|
@ -200,9 +200,9 @@ class showstl(wx.Window):
|
|||
|
||||
def repaint(self, event):
|
||||
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}
|
||||
if dc is None:
|
||||
dc = wx.ClientDC(self)
|
||||
|
@ -231,7 +231,7 @@ class showstl(wx.Window):
|
|||
bm = wx.BitmapFromImage(im)
|
||||
dcs.SelectObject(bm)
|
||||
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))):
|
||||
# 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:
|
||||
|
@ -242,29 +242,29 @@ class showstl(wx.Window):
|
|||
|
||||
|
||||
class stlwin(wx.Frame):
|
||||
def __init__(self, size=(800, 580), callback=None, parent=None):
|
||||
wx.Frame.__init__(self, parent, title=_("Plate building tool"), size=size)
|
||||
def __init__(self, size = (800, 580), callback = None, parent = None):
|
||||
wx.Frame.__init__(self, parent, title = _("Plate building tool"), size = size)
|
||||
self.SetIcon(wx.Icon(pixmapfile("plater.ico"), wx.BITMAP_TYPE_ICO))
|
||||
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.l = wx.ListBox(self.panel, size=(300, 180), pos=(0, 30))
|
||||
self.cl = wx.Button(self.panel, label=_("Clear"), pos=(0, 205))
|
||||
self.lb = wx.Button(self.panel, label=_("Load"), pos=(0, 0))
|
||||
self.l = wx.ListBox(self.panel, size = (300, 180), pos = (0, 30))
|
||||
self.cl = wx.Button(self.panel, label = _("Clear"), pos = (0, 205))
|
||||
self.lb = wx.Button(self.panel, label = _("Load"), pos = (0, 0))
|
||||
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)
|
||||
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.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.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.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.db = wx.Button(self.panel, label=_("Delete"), pos=(0, 305))
|
||||
self.ab = wx.Button(self.panel, label=_("Auto"), pos=(0, 330))
|
||||
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.db = wx.Button(self.panel, label = _("Delete"), pos = (0, 305))
|
||||
self.ab = wx.Button(self.panel, label = _("Auto"), pos = (0, 330))
|
||||
self.cl.Bind(wx.EVT_BUTTON, self.clear)
|
||||
self.lb.Bind(wx.EVT_BUTTON, self.right)
|
||||
self.sb.Bind(wx.EVT_BUTTON, self.snap)
|
||||
|
@ -336,25 +336,25 @@ class stlwin(wx.Frame):
|
|||
def center(self, event):
|
||||
i = self.l.GetSelection()
|
||||
if i != -1:
|
||||
m = self.models[self.l.GetString(i)]
|
||||
m.offsets = [100, 100, m.offsets[2]]
|
||||
self.Refresh()
|
||||
m = self.models[self.l.GetString(i)]
|
||||
m.offsets = [100, 100, m.offsets[2]]
|
||||
self.Refresh()
|
||||
|
||||
def snap(self, event):
|
||||
i = self.l.GetSelection()
|
||||
if i != -1:
|
||||
m = self.models[self.l.GetString(i)]
|
||||
m.offsets[2] = -1.0 * min(m.facetsminz)[0]
|
||||
#print m.offsets[2]
|
||||
self.Refresh()
|
||||
m = self.models[self.l.GetString(i)]
|
||||
m.offsets[2] = -1.0 * min(m.facetsminz)[0]
|
||||
#print m.offsets[2]
|
||||
self.Refresh()
|
||||
|
||||
def delete(self, event):
|
||||
i = self.l.GetSelection()
|
||||
if i != -1:
|
||||
del self.models[self.l.GetString(i)]
|
||||
self.l.Delete(i)
|
||||
self.l.Select(self.l.GetCount() - 1)
|
||||
self.Refresh()
|
||||
del self.models[self.l.GetString(i)]
|
||||
self.l.Delete(i)
|
||||
self.l.Select(self.l.GetCount() - 1)
|
||||
self.Refresh()
|
||||
|
||||
def done(self, event, cb):
|
||||
try:
|
||||
|
@ -368,7 +368,7 @@ class stlwin(wx.Frame):
|
|||
self.Destroy()
|
||||
|
||||
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;)"))
|
||||
if(dlg.ShowModal() == wx.ID_OK):
|
||||
name = dlg.GetPath()
|
||||
|
@ -393,7 +393,7 @@ class stlwin(wx.Frame):
|
|||
print _("wrote %s") % name
|
||||
|
||||
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"))
|
||||
if(dlg.ShowModal() == wx.ID_OK):
|
||||
name = dlg.GetPath()
|
||||
|
@ -443,7 +443,7 @@ class stlwin(wx.Frame):
|
|||
self.Refresh()
|
||||
#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]
|
||||
c = 1
|
||||
while newname in self.models:
|
||||
|
|
|
@ -0,0 +1,396 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# 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/>.
|
||||
|
||||
from serial import Serial, SerialException
|
||||
from threading import Thread
|
||||
from select import error as SelectError
|
||||
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():
|
||||
def __init__(self, port = None, baud = None):
|
||||
"""Initializes a printcore instance. Pass the port and baud rate to connect immediately
|
||||
"""
|
||||
self.baud = None
|
||||
self.port = None
|
||||
self.printer = None #Serial instance connected to the printer, None when disconnected
|
||||
self.clear = 0 #clear to send, enabled after responses
|
||||
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.mainqueue = []
|
||||
self.priqueue = []
|
||||
self.queueindex = 0
|
||||
self.lineno = 0
|
||||
self.resendfrom = -1
|
||||
self.paused = False
|
||||
self.sentlines = {}
|
||||
self.log = []
|
||||
self.sent = []
|
||||
self.tempcb = None #impl (wholeline)
|
||||
self.recvcb = None #impl (wholeline)
|
||||
self.sendcb = None #impl (wholeline)
|
||||
self.errorcb = None #impl (wholeline)
|
||||
self.startcb = None #impl ()
|
||||
self.endcb = None #impl ()
|
||||
self.onlinecb = None #impl ()
|
||||
self.loud = False #emit sent and received lines to terminal
|
||||
self.greetings = ['start','Grbl ']
|
||||
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:
|
||||
self.connect(port, baud)
|
||||
|
||||
def disconnect(self):
|
||||
"""Disconnects from printer and pauses the print
|
||||
"""
|
||||
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 = None
|
||||
self.online = False
|
||||
self.printing = False
|
||||
|
||||
def connect(self, port = None, baud = None):
|
||||
"""Set port and baudrate if given, then connect to printer
|
||||
"""
|
||||
if self.printer:
|
||||
self.disconnect()
|
||||
if port is not None:
|
||||
self.port = port
|
||||
if baud is not None:
|
||||
self.baud = baud
|
||||
if self.port is not None and self.baud is not None:
|
||||
disable_hup(self.port)
|
||||
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):
|
||||
"""Reset the printer
|
||||
"""
|
||||
if self.printer:
|
||||
self.printer.setDTR(1)
|
||||
time.sleep(0.2)
|
||||
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):
|
||||
"""This function acts on messages from the firmware
|
||||
"""
|
||||
self.clear = True
|
||||
if not self.printing:
|
||||
self._listen_until_online()
|
||||
while self._listen_can_continue():
|
||||
line = self._readline()
|
||||
if line == None:
|
||||
break
|
||||
if line.startswith('DEBUG_'):
|
||||
continue
|
||||
if line.startswith(tuple(self.greetings)) or line.startswith('ok'):
|
||||
self.clear = True
|
||||
if line.startswith('ok') and "T:" in line and self.tempcb:
|
||||
#callback for temp, status, whatever
|
||||
try: self.tempcb(line)
|
||||
except: pass
|
||||
elif line.startswith('Error'):
|
||||
if self.errorcb:
|
||||
#callback for errors
|
||||
try: self.errorcb(line)
|
||||
except: pass
|
||||
# Teststrings for resend parsing # Firmware exp. result
|
||||
# line="rs N2 Expected checksum 67" # Teacup 2
|
||||
if line.lower().startswith("resend") or line.startswith("rs"):
|
||||
line = line.replace("N:"," ").replace("N"," ").replace(":"," ")
|
||||
linewords = line.split()
|
||||
while len(linewords) != 0:
|
||||
try:
|
||||
toresend = int(linewords.pop(0))
|
||||
self.resendfrom = toresend
|
||||
#print str(toresend)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
self.clear = True
|
||||
self.clear = True
|
||||
|
||||
def _checksum(self, command):
|
||||
return reduce(lambda x, y:x^y, map(ord, command))
|
||||
|
||||
def startprint(self, data, startindex = 0):
|
||||
"""Start a print, data is an array of gcode commands.
|
||||
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.
|
||||
Printing will then start in a parallel thread.
|
||||
"""
|
||||
if self.printing or not self.online or not self.printer:
|
||||
return False
|
||||
self.printing = True
|
||||
self.mainqueue = [] + data
|
||||
self.lineno = 0
|
||||
self.queueindex = startindex
|
||||
self.resendfrom = -1
|
||||
self._send("M110", -1, True)
|
||||
if len(data) == 0:
|
||||
return True
|
||||
self.clear = False
|
||||
self.print_thread = Thread(target = self._print)
|
||||
self.print_thread.start()
|
||||
return True
|
||||
|
||||
def pause(self):
|
||||
"""Pauses the print, saving the current position.
|
||||
"""
|
||||
self.paused = True
|
||||
self.printing = False
|
||||
self.print_thread.join()
|
||||
self.print_thread = None
|
||||
|
||||
def resume(self):
|
||||
"""Resumes a paused print.
|
||||
"""
|
||||
self.paused = False
|
||||
self.printing = True
|
||||
self.print_thread = Thread(target = self._print)
|
||||
self.print_thread.start()
|
||||
|
||||
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
|
||||
"""
|
||||
|
||||
if self.online:
|
||||
if self.printing:
|
||||
self.mainqueue.append(command)
|
||||
else:
|
||||
while self.printer and self.printing and not self.clear:
|
||||
time.sleep(0.001)
|
||||
if wait == 0 and self.wait > 0:
|
||||
wait = self.wait
|
||||
if wait > 0:
|
||||
self.clear = False
|
||||
self._send(command, self.lineno, True)
|
||||
self.lineno += 1
|
||||
while wait > 0 and self.printer and self.printing and not self.clear:
|
||||
time.sleep(0.001)
|
||||
wait -= 1
|
||||
else:
|
||||
print "Not connected to printer."
|
||||
|
||||
def send_now(self, command, wait = 0):
|
||||
"""Sends a command to the printer ahead of the command queue, without a checksum
|
||||
"""
|
||||
if self.online or force:
|
||||
if self.printing:
|
||||
self.priqueue.append(command)
|
||||
else:
|
||||
while self.printer and self.printing and not self.clear:
|
||||
time.sleep(0.001)
|
||||
if wait == 0 and self.wait > 0:
|
||||
wait = self.wait
|
||||
if wait > 0:
|
||||
self.clear = False
|
||||
self._send(command)
|
||||
while (wait > 0) and self.printer and self.printing and not self.clear:
|
||||
time.sleep(0.001)
|
||||
wait -= 1
|
||||
else:
|
||||
print "Not connected to printer."
|
||||
|
||||
def _print(self):
|
||||
if self.startcb:
|
||||
#callback for printing started
|
||||
try: self.startcb()
|
||||
except: pass
|
||||
while self.printing and self.printer and self.online:
|
||||
self._sendnext()
|
||||
self.sentlines = {}
|
||||
self.log = []
|
||||
self.sent = []
|
||||
if self.endcb:
|
||||
#callback for printing done
|
||||
try: self.endcb()
|
||||
except: pass
|
||||
|
||||
def _sendnext(self):
|
||||
if not self.printer:
|
||||
return
|
||||
while self.printer and self.printing and not self.clear:
|
||||
time.sleep(0.001)
|
||||
self.clear = False
|
||||
if not (self.printing and self.printer and self.online):
|
||||
self.clear = True
|
||||
return
|
||||
if self.resendfrom < self.lineno and self.resendfrom > -1:
|
||||
self._send(self.sentlines[self.resendfrom], self.resendfrom, False)
|
||||
self.resendfrom += 1
|
||||
return
|
||||
self.resendfrom = -1
|
||||
for i in self.priqueue[:]:
|
||||
self._send(i)
|
||||
del self.priqueue[0]
|
||||
return
|
||||
if self.printing and self.queueindex < len(self.mainqueue):
|
||||
tline = self.mainqueue[self.queueindex]
|
||||
tline = tline.split(";")[0]
|
||||
if len(tline) > 0:
|
||||
self._send(tline, self.lineno, True)
|
||||
self.lineno += 1
|
||||
else:
|
||||
self.clear = True
|
||||
self.queueindex += 1
|
||||
else:
|
||||
self.printing = False
|
||||
self.clear = True
|
||||
if not self.paused:
|
||||
self.queueindex = 0
|
||||
self.lineno = 0
|
||||
self._send("M110", -1, True)
|
||||
|
||||
def _send(self, command, lineno = 0, calcchecksum = False):
|
||||
if calcchecksum:
|
||||
prefix = "N" + str(lineno) + " " + command
|
||||
command = prefix + "*" + str(self._checksum(prefix))
|
||||
if "M110" not in command:
|
||||
self.sentlines[lineno] = command
|
||||
if self.printer:
|
||||
self.sent.append(command)
|
||||
if self.loud:
|
||||
print "SENT: ", command
|
||||
if self.sendcb:
|
||||
try: self.sendcb(command)
|
||||
except: pass
|
||||
try:
|
||||
self.printer.write(str(command+"\n"))
|
||||
except SerialException, e:
|
||||
print "Can't write to printer (disconnected?)."
|
||||
|
||||
if __name__ == '__main__':
|
||||
baud = 115200
|
||||
loud = False
|
||||
statusreport = False
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "h,b:,v,s",
|
||||
["help", "baud", "verbose", "statusreport"])
|
||||
except getopt.GetoptError, err:
|
||||
print str(err)
|
||||
sys.exit(2)
|
||||
for o, a in opts:
|
||||
if o in ('-h', '--help'):
|
||||
# FIXME: Fix help
|
||||
print "Opts are: --help , -b --baud = baudrate, -v --verbose, -s --statusreport"
|
||||
sys.exit(1)
|
||||
if o in ('-b', '--baud'):
|
||||
baud = int(a)
|
||||
if o in ('-v','--verbose'):
|
||||
loud = True
|
||||
elif o in ('-s','--statusreport'):
|
||||
statusreport = True
|
||||
|
||||
if len (args) > 1:
|
||||
port = args[-2]
|
||||
filename = args[-1]
|
||||
print "Printing: %s on %s with baudrate %d" % (filename, port, baud)
|
||||
else:
|
||||
print "Usage: python [-h|-b|-v|-s] printcore.py /dev/tty[USB|ACM]x filename.gcode"
|
||||
sys.exit(2)
|
||||
p = printcore(port, baud)
|
||||
p.loud = loud
|
||||
time.sleep(2)
|
||||
gcode = [i.replace("\n", "") for i in open(filename)]
|
||||
p.startprint(gcode)
|
||||
|
||||
try:
|
||||
if statusreport:
|
||||
p.loud = False
|
||||
sys.stdout.write("Progress: 00.0%")
|
||||
sys.stdout.flush()
|
||||
while p.printing:
|
||||
time.sleep(1)
|
||||
if statusreport:
|
||||
sys.stdout.write("\b\b\b\b%02.1f%%" % (100 * float(p.queueindex) / len(p.mainqueue),) )
|
||||
sys.stdout.flush()
|
||||
p.disconnect()
|
||||
sys.exit(0)
|
||||
except:
|
||||
p.disconnect()
|
|
@ -16,13 +16,13 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
|
|||
self.cancelButton = wx.Button(self, wx.ID_CANCEL, "")
|
||||
self.Bind(wx.EVT_BUTTON, self.OnExit, self.cancelButton)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnSave, self.okButton)
|
||||
|
||||
|
||||
"""
|
||||
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.
|
||||
|
||||
|
||||
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 = {
|
||||
'dimension':['Filament Diameter (mm):','Retraction Distance (millimeters):', 'Retraction Distance (millimeters):','Extruder Retraction Speed (mm/s):'],
|
||||
|
@ -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):',],
|
||||
'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.scrollbarPanel.SetSizer(self.settingsSizer)
|
||||
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
self.Show()
|
||||
|
||||
|
||||
def __set_properties(self):
|
||||
self.profileName = skeinforge_profile.getProfileName(skeinforge_profile.getCraftTypeName())
|
||||
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'):
|
||||
self.SetMinSize(wx.DLG_SZE(self, (465, 370)))
|
||||
else:
|
||||
self.SetSize(wx.DLG_SZE(self, (465, 325)))
|
||||
|
||||
|
||||
self.SetPosition((0, 0))
|
||||
self.scrollbarPanel.SetScrollRate(10, 10)
|
||||
|
||||
|
||||
def __do_layout(self):
|
||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
actionsSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
@ -65,56 +65,56 @@ class SkeinforgeQuickEditDialog(wx.Dialog):
|
|||
mainSizer.Add(actionsSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 5)
|
||||
self.SetSizer(mainSizer)
|
||||
self.Layout()
|
||||
|
||||
|
||||
def getProfileSettings(self):
|
||||
settingsSizer = wx.GridBagSizer(hgap=2, vgap=1)
|
||||
settingsSizer = wx.GridBagSizer(hgap = 2, vgap = 1)
|
||||
settingsRow = 0
|
||||
|
||||
|
||||
for craftName in sorted(self.moduleSettingsMap.keys()):
|
||||
|
||||
|
||||
craftStaticBox = wx.StaticBox(self.scrollbarPanel, -1, craftName.capitalize())
|
||||
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
|
||||
if (os.name == 'nt'):
|
||||
craftStaticBoxSizer.SetMinSize((320, -1))
|
||||
else:
|
||||
else:
|
||||
craftStaticBoxSizer.SetMinSize((450, -1))
|
||||
pluginModule = archive.getModuleWithPath(os.path.join(skeinforge_craft.getPluginsDirectoryPath(), craftName))
|
||||
repo = pluginModule.getNewRepository()
|
||||
|
||||
|
||||
for setting in settings.getReadRepository(repo).preferences:
|
||||
if setting.name in self.moduleSettingsMap[craftName]:
|
||||
|
||||
settingSizer = wx.GridBagSizer(hgap=2, vgap=2)
|
||||
|
||||
settingSizer = wx.GridBagSizer(hgap = 2, vgap = 2)
|
||||
settingSizer.AddGrowableCol(0)
|
||||
settingRow = 0
|
||||
settingLabel = wx.StaticText(self.scrollbarPanel, -1, setting.name)
|
||||
settingLabel.Wrap(400)
|
||||
settingSizer.Add(settingLabel, pos=(settingRow, 0))
|
||||
|
||||
settingSizer.Add(settingLabel, pos = (settingRow, 0))
|
||||
|
||||
if (isinstance(setting.value, bool)):
|
||||
checkbox = wx.CheckBox(self.scrollbarPanel)
|
||||
checkbox.SetName(craftName + '.' + setting.name)
|
||||
checkbox.SetValue(setting.value)
|
||||
settingSizer.Add(checkbox, pos=(settingRow, 1))
|
||||
settingSizer.AddSpacer((25, -1), pos=(settingRow, 2))
|
||||
settingSizer.Add(checkbox, pos = (settingRow, 1))
|
||||
settingSizer.AddSpacer((25, -1), pos = (settingRow, 2))
|
||||
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)
|
||||
settingSizer.Add(textCtrl, pos=(settingRow, 1))
|
||||
|
||||
settingSizer.Add(textCtrl, pos = (settingRow, 1))
|
||||
|
||||
craftStaticBoxSizer.Add(settingSizer, 1, wx.EXPAND, 0)
|
||||
settingRow += 1
|
||||
col = settingsRow % 2
|
||||
settingsSizer.Add(craftStaticBoxSizer, pos=(settingsRow - col, col))
|
||||
settingsSizer.Add(craftStaticBoxSizer, pos = (settingsRow - col, col))
|
||||
settingsRow += 1
|
||||
|
||||
return settingsSizer
|
||||
|
||||
def OnExit(self, e):
|
||||
self.Destroy()
|
||||
|
||||
|
||||
def OnSave(self, e):
|
||||
for x in self.scrollbarPanel.GetChildren():
|
||||
if (isinstance(x, (wx.CheckBox, wx.TextCtrl))):
|
||||
|
|
|
@ -11,9 +11,9 @@ import shutil
|
|||
|
||||
class MyFrame(wx.Frame):
|
||||
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')
|
||||
|
||||
|
||||
# milliseconds per frame
|
||||
self.delay = 60
|
||||
# number of loops
|
||||
|
@ -41,7 +41,7 @@ class MyFrame(wx.Frame):
|
|||
self.image_list = []
|
||||
for image_file in file_list:
|
||||
self.image_list.append(wx.Bitmap(image_file))
|
||||
|
||||
|
||||
# bind the panel to the paint event
|
||||
wx.EVT_PAINT(self, self.onPaint)
|
||||
|
||||
|
@ -49,7 +49,7 @@ class MyFrame(wx.Frame):
|
|||
if self.mytmpdir:
|
||||
shutil.rmtree(self.mytmpdir)
|
||||
|
||||
def onPaint(self, event=None):
|
||||
def onPaint(self, event = None):
|
||||
# this is the wxPython drawing surface/canvas
|
||||
dc = wx.PaintDC(self)
|
||||
while self.loops:
|
||||
|
@ -59,7 +59,7 @@ class MyFrame(wx.Frame):
|
|||
w, h = bmp.GetSize()
|
||||
info = "%s %dx%d" % (self.name_list[ix], w, h)
|
||||
self.SetTitle(info)
|
||||
#self.SetSize((w,h))
|
||||
#self.SetSize((w, h))
|
||||
# draw the image
|
||||
dc.DrawBitmap(bmp, 0, 0, True)
|
||||
wx.MilliSleep(self.delay)
|
||||
|
@ -73,4 +73,4 @@ width = 800
|
|||
frameoffset = 35
|
||||
height = 600 + frameoffset
|
||||
MyFrame(None, (width, height)).Show()
|
||||
app.MainLoop()
|
||||
app.MainLoop()
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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
|
||||
Library. This has been done to prevent users of the Library from being
|
||||
denied access or the ability to use future improvements.
|
||||
|
@ -66,10 +66,10 @@ class BufferedCanvas(wx.Panel):
|
|||
def __init__(self,
|
||||
parent,
|
||||
ID=-1,
|
||||
pos=wx.DefaultPosition,
|
||||
size=wx.DefaultSize,
|
||||
style=wx.NO_FULL_REPAINT_ON_RESIZE|wx.WANTS_CHARS):
|
||||
wx.Panel.__init__(self,parent,ID,pos,size,style)
|
||||
pos = wx.DefaultPosition,
|
||||
size = wx.DefaultSize,
|
||||
style = wx.NO_FULL_REPAINT_ON_RESIZE|wx.WANTS_CHARS):
|
||||
wx.Panel.__init__(self, parent, ID, pos, size, style)
|
||||
|
||||
# Bind events
|
||||
self.Bind(wx.EVT_PAINT, self.onPaint)
|
||||
|
@ -83,7 +83,7 @@ class BufferedCanvas(wx.Panel):
|
|||
## General methods
|
||||
##
|
||||
|
||||
def draw(self,dc):
|
||||
def draw(self, dc):
|
||||
"""
|
||||
Stub: called when the canvas needs to be re-drawn.
|
||||
"""
|
||||
|
@ -94,9 +94,9 @@ class BufferedCanvas(wx.Panel):
|
|||
Causes the canvas to be updated.
|
||||
"""
|
||||
self.Refresh()
|
||||
|
||||
|
||||
def getWidthHeight(self):
|
||||
width,height = self.GetClientSizeTuple()
|
||||
width, height = self.GetClientSizeTuple()
|
||||
if width == 0:
|
||||
width = 1
|
||||
if height == 0:
|
||||
|
|
|
@ -2,150 +2,150 @@
|
|||
#Interactive RepRap e axis calibration program
|
||||
#(C) Nathan Zadoks 2011
|
||||
#Licensed under CC-BY-SA or GPLv2 and higher - Pick your poison.
|
||||
s=300 #Extrusion speed (mm/min)
|
||||
n=100 #Default length to extrude
|
||||
m= 0 #User-entered measured extrusion length
|
||||
k=300 #Default amount of steps per mm
|
||||
port='/dev/ttyUSB0' #Default serial port to connect to printer
|
||||
temp=210 #Default extrusion temperature
|
||||
s = 300 #Extrusion speed (mm/min)
|
||||
n = 100 #Default length to extrude
|
||||
m= 0 #User-entered measured extrusion length
|
||||
k = 300 #Default amount of steps per mm
|
||||
port='/dev/ttyUSB0' #Default serial port to connect to printer
|
||||
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:
|
||||
from printdummy import printcore
|
||||
from printdummy import printcore
|
||||
except ImportError:
|
||||
from printcore import printcore
|
||||
import time,getopt,sys,os
|
||||
from printcore import printcore
|
||||
import time, getopt, sys, os
|
||||
|
||||
def float_input(prompt=''):
|
||||
import sys
|
||||
f=None
|
||||
while f==None:
|
||||
s=raw_input(prompt)
|
||||
try:
|
||||
f=float(s)
|
||||
except ValueError:
|
||||
sys.stderr.write("Not a valid floating-point number.\n")
|
||||
sys.stderr.flush()
|
||||
return f
|
||||
def wait(t,m=''):
|
||||
import time,sys
|
||||
sys.stdout.write(m+'['+(' '*t)+']\r'+m+'[')
|
||||
sys.stdout.flush()
|
||||
for i in range(t):
|
||||
for s in ['|\b','/\b','-\b','\\\b','|']:
|
||||
sys.stdout.write(s)
|
||||
sys.stdout.flush()
|
||||
time.sleep(1.0/5)
|
||||
print
|
||||
import sys
|
||||
f = None
|
||||
while f == None:
|
||||
s = raw_input(prompt)
|
||||
try:
|
||||
f = float(s)
|
||||
except ValueError:
|
||||
sys.stderr.write("Not a valid floating-point number.\n")
|
||||
sys.stderr.flush()
|
||||
return f
|
||||
def wait(t, m=''):
|
||||
import time, sys
|
||||
sys.stdout.write(m+'['+(' '*t)+']\r'+m+'[')
|
||||
sys.stdout.flush()
|
||||
for i in range(t):
|
||||
for s in ['|\b','/\b','-\b','\\\b','|']:
|
||||
sys.stdout.write(s)
|
||||
sys.stdout.flush()
|
||||
time.sleep(1.0/5)
|
||||
print
|
||||
def w(s):
|
||||
sys.stdout.write(s)
|
||||
sys.stdout.flush()
|
||||
sys.stdout.write(s)
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
def heatup(p,temp,s=0):
|
||||
curtemp=gettemp(p)
|
||||
p.send_now('M109 S%03d'%temp)
|
||||
p.temp=0
|
||||
if not s: w("Heating extruder up..")
|
||||
f=False
|
||||
while curtemp<=(temp-1):
|
||||
p.send_now('M105')
|
||||
time.sleep(0.5)
|
||||
if not f:
|
||||
time.sleep(1.5)
|
||||
f=True
|
||||
curtemp=gettemp(p)
|
||||
if curtemp: w(u"\rHeating extruder up.. %3d \xb0C"%curtemp)
|
||||
if s: print
|
||||
else: print "\nReady."
|
||||
def heatup(p, temp, s = 0):
|
||||
curtemp = gettemp(p)
|
||||
p.send_now('M109 S%03d'%temp)
|
||||
p.temp = 0
|
||||
if not s: w("Heating extruder up..")
|
||||
f = False
|
||||
while curtemp<=(temp-1):
|
||||
p.send_now('M105')
|
||||
time.sleep(0.5)
|
||||
if not f:
|
||||
time.sleep(1.5)
|
||||
f = True
|
||||
curtemp = gettemp(p)
|
||||
if curtemp: w(u"\rHeating extruder up.. %3d \xb0C"%curtemp)
|
||||
if s: print
|
||||
else: print "\nReady."
|
||||
|
||||
def gettemp(p):
|
||||
try: p.logl
|
||||
except: setattr(p,'logl',0)
|
||||
try: p.temp
|
||||
except: setattr(p,'temp',0)
|
||||
for n in range(p.logl,len(p.log)):
|
||||
line=p.log[n]
|
||||
if 'T:' in line:
|
||||
try:
|
||||
setattr(p,'temp',int(line.split('T:')[1].split()[0]))
|
||||
except: print line
|
||||
p.logl=len(p.log)
|
||||
return p.temp
|
||||
try: p.logl
|
||||
except: setattr(p,'logl',0)
|
||||
try: p.temp
|
||||
except: setattr(p,'temp',0)
|
||||
for n in range(p.logl, len(p.log)):
|
||||
line = p.log[n]
|
||||
if 'T:' in line:
|
||||
try:
|
||||
setattr(p,'temp',int(line.split('T:')[1].split()[0]))
|
||||
except: print line
|
||||
p.logl = len(p.log)
|
||||
return p.temp
|
||||
if not os.path.exists(port):
|
||||
port=0
|
||||
port = 0
|
||||
|
||||
#Parse options
|
||||
help=u"""
|
||||
help = u"""
|
||||
%s [ -l DISTANCE ] [ -s STEPS ] [ -t TEMP ] [ -p PORT ]
|
||||
-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)
|
||||
-t --temp Extrusion temperature in degrees Celsius (default: %d \xb0C, max %d \xb0C)
|
||||
-p --port Serial port the printer is connected to (default: %s)
|
||||
-h --help This cruft.
|
||||
"""[1:-1].encode('utf-8')%(sys.argv[0],n,k,temp,tempmax,port if port else 'auto')
|
||||
-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)
|
||||
-t --temp Extrusion temperature in degrees Celsius (default: %d \xb0C, max %d \xb0C)
|
||||
-p --port Serial port the printer is connected to (default: %s)
|
||||
-h --help This cruft.
|
||||
"""[1:-1].encode('utf-8')%(sys.argv[0], n, k, temp, tempmax, port if port else 'auto')
|
||||
try:
|
||||
opts,args=getopt.getopt(sys.argv[1:],"hl:s:t:p:",["help","length=","steps=","temp=","port="])
|
||||
except getopt.GetoptError,err:
|
||||
print str(err)
|
||||
print help
|
||||
sys.exit(2)
|
||||
for o,a in opts:
|
||||
if o in ('-h','--help'):
|
||||
print help
|
||||
sys.exit()
|
||||
elif o in ('-l','--length'):
|
||||
n=float(a)
|
||||
elif o in ('-s','--steps'):
|
||||
k=int(a)
|
||||
elif o in ('-t','--temp'):
|
||||
temp=int(a)
|
||||
if temp>=tempmax:
|
||||
print (u'%d \xb0C? Are you insane?'.encode('utf-8')%temp)+(" That's over nine thousand!" if temp>9000 else '')
|
||||
sys.exit(255)
|
||||
elif o in ('-p','--port'):
|
||||
port=a
|
||||
opts, args = getopt.getopt(sys.argv[1:],"hl:s:t:p:",["help", "length=", "steps=", "temp=", "port="])
|
||||
except getopt.GetoptError, err:
|
||||
print str(err)
|
||||
print help
|
||||
sys.exit(2)
|
||||
for o, a in opts:
|
||||
if o in ('-h','--help'):
|
||||
print help
|
||||
sys.exit()
|
||||
elif o in ('-l','--length'):
|
||||
n = float(a)
|
||||
elif o in ('-s','--steps'):
|
||||
k = int(a)
|
||||
elif o in ('-t','--temp'):
|
||||
temp = int(a)
|
||||
if temp>=tempmax:
|
||||
print (u'%d \xb0C? Are you insane?'.encode('utf-8')%temp)+(" That's over nine thousand!" if temp>9000 else '')
|
||||
sys.exit(255)
|
||||
elif o in ('-p','--port'):
|
||||
port = a
|
||||
|
||||
#Show initial parameters
|
||||
print "Initial parameters"
|
||||
print "Steps per mm: %3d steps"%k
|
||||
print "Length extruded: %3d mm"%n
|
||||
print
|
||||
print
|
||||
print "Serial port: %s"%(port if port else 'auto')
|
||||
|
||||
p=None
|
||||
p = None
|
||||
try:
|
||||
#Connect to printer
|
||||
w("Connecting to printer..")
|
||||
try:
|
||||
p=printcore(port,115200)
|
||||
except:
|
||||
print 'Error.'
|
||||
raise
|
||||
while not p.online:
|
||||
time.sleep(1)
|
||||
w('.')
|
||||
print " connected."
|
||||
|
||||
heatup(p,temp)
|
||||
|
||||
#Calibration loop
|
||||
while n!=m:
|
||||
heatup(p,temp,True)
|
||||
p.send_now("G92 E0") #Reset e axis
|
||||
p.send_now("G1 E%d F%d"%(n,s)) #Extrude length of filament
|
||||
wait(t,'Extruding.. ')
|
||||
m=float_input("How many millimeters of filament were extruded? ")
|
||||
if m==0: continue
|
||||
if n!=m:
|
||||
k=(n/m)*k
|
||||
p.send_now("M92 E%d"%int(round(k))) #Set new step count
|
||||
print "Steps per mm: %3d steps"%k #Tell user
|
||||
print 'Calibration completed.' #Yay!
|
||||
#Connect to printer
|
||||
w("Connecting to printer..")
|
||||
try:
|
||||
p = printcore(port, 115200)
|
||||
except:
|
||||
print 'Error.'
|
||||
raise
|
||||
while not p.online:
|
||||
time.sleep(1)
|
||||
w('.')
|
||||
print " connected."
|
||||
|
||||
heatup(p, temp)
|
||||
|
||||
#Calibration loop
|
||||
while n!=m:
|
||||
heatup(p, temp, True)
|
||||
p.send_now("G92 E0") #Reset e axis
|
||||
p.send_now("G1 E%d F%d"%(n, s)) #Extrude length of filament
|
||||
wait(t,'Extruding.. ')
|
||||
m = float_input("How many millimeters of filament were extruded? ")
|
||||
if m == 0: continue
|
||||
if n!=m:
|
||||
k = (n/m)*k
|
||||
p.send_now("M92 E%d"%int(round(k))) #Set new step count
|
||||
print "Steps per mm: %3d steps"%k #Tell user
|
||||
print 'Calibration completed.' #Yay!
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
pass
|
||||
finally:
|
||||
if p: p.disconnect()
|
||||
if p: p.disconnect()
|
||||
|
|
|
@ -19,8 +19,8 @@ import threading
|
|||
class GLPanel(wx.Panel):
|
||||
'''A simple class for using OpenGL with wxPython.'''
|
||||
|
||||
def __init__(self, parent, id, pos=wx.DefaultPosition,
|
||||
size=wx.DefaultSize, style=0):
|
||||
def __init__(self, parent, id, pos = wx.DefaultPosition,
|
||||
size = wx.DefaultSize, style = 0):
|
||||
# Forcing a no full repaint to stop flickering
|
||||
style = style | wx.NO_FULL_REPAINT_ON_RESIZE
|
||||
#call super function
|
||||
|
@ -33,7 +33,7 @@ class GLPanel(wx.Panel):
|
|||
glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit
|
||||
# Create the canvas
|
||||
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.SetSizer(self.sizer)
|
||||
#self.sizer.Fit(self)
|
||||
|
@ -200,7 +200,7 @@ def _dist(dist):
|
|||
class gcpoint(object):
|
||||
"""gcode point
|
||||
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.y = y
|
||||
self.z = z
|
||||
|
@ -210,10 +210,10 @@ class gcpoint(object):
|
|||
|
||||
class gcline(object):
|
||||
"""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()
|
||||
"""
|
||||
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:
|
||||
self.prev_gcline = gcpoint()
|
||||
else:
|
||||
|
@ -255,7 +255,7 @@ class gcline(object):
|
|||
self.orgline,
|
||||
)
|
||||
|
||||
def calc_delta(self, prev_gcline=None):
|
||||
def calc_delta(self, prev_gcline = None):
|
||||
if prev_gcline is None:
|
||||
prev_gcline = self.prev_gcline
|
||||
if self.prev_gcline is not None:
|
||||
|
@ -290,7 +290,7 @@ class gcline(object):
|
|||
]
|
||||
def glcolor(self, upper_limit = None, lower_limit = 0, max_feedrate = 0):
|
||||
if self.extrusion_ratio == 0:
|
||||
return [255,255,255,0,0,0]
|
||||
return [255, 255, 255, 0, 0, 0]
|
||||
else:
|
||||
blue_color = 0
|
||||
green_color = 0
|
||||
|
@ -312,7 +312,7 @@ class gcline(object):
|
|||
blue_color = 255
|
||||
if 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):
|
||||
|
@ -340,7 +340,7 @@ class gcview(object):
|
|||
"""gcode visualiser
|
||||
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:
|
||||
return
|
||||
print "Loading %s lines" % (len(lines))
|
||||
|
@ -430,7 +430,7 @@ class gcview(object):
|
|||
else:
|
||||
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
|
||||
return r
|
||||
return None
|
||||
|
@ -524,7 +524,7 @@ def mulquat(q1, rq):
|
|||
|
||||
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)
|
||||
self.batches = []
|
||||
self.rot = 0
|
||||
|
@ -553,7 +553,7 @@ class TestGlPanel(GLPanel):
|
|||
def forceresize(self):
|
||||
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
|
||||
|
||||
def move_shape(self, delta):
|
||||
|
@ -605,7 +605,7 @@ class TestGlPanel(GLPanel):
|
|||
p1y = -(float(p1[1]) - sz[1] / 2) / (sz[1] / 2)
|
||||
p2x = (float(p2[0]) - sz[0] / 2) / (sz[0] / 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)
|
||||
if self.rot:
|
||||
self.basequat = mulquat(self.basequat, quat)
|
||||
|
@ -768,7 +768,7 @@ class TestGlPanel(GLPanel):
|
|||
|
||||
def drawmodel(self, m, n):
|
||||
batch = pyglet.graphics.Batch()
|
||||
stl = stlview(m.facets, batch=batch)
|
||||
stl = stlview(m.facets, batch = batch)
|
||||
m.batch = batch
|
||||
m.animoffset = 300
|
||||
#print m
|
||||
|
@ -907,8 +907,8 @@ class TestGlPanel(GLPanel):
|
|||
class GCFrame(wx.Frame):
|
||||
'''A simple class for using OpenGL with wxPython.'''
|
||||
|
||||
def __init__(self, parent, ID, title, pos=wx.DefaultPosition,
|
||||
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
|
||||
def __init__(self, parent, ID, title, pos = wx.DefaultPosition,
|
||||
size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
|
||||
super(GCFrame, self).__init__(parent, ID, title, pos, (size[0] + 150, size[1]), style)
|
||||
|
||||
class d:
|
||||
|
@ -921,22 +921,22 @@ class GCFrame(wx.Frame):
|
|||
m.curlayer = -1
|
||||
m.scale = [1.0, 1.0, 1.0]
|
||||
m.batch = pyglet.graphics.Batch()
|
||||
m.gc = gcview([], batch=m.batch)
|
||||
m.gc = gcview([], batch = m.batch)
|
||||
self.models = {"GCODE": m}
|
||||
self.l = d()
|
||||
self.modelindex = 0
|
||||
self.GLPanel1 = TestGlPanel(self, size)
|
||||
|
||||
def addfile(self, gcode=[]):
|
||||
def addfile(self, gcode = []):
|
||||
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)
|
||||
|
||||
def clear(self):
|
||||
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)
|
||||
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):
|
|||
|
||||
|
||||
def main():
|
||||
app = wx.App(redirect=False)
|
||||
frame = GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size=(400, 400))
|
||||
app = wx.App(redirect = False)
|
||||
frame = GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size = (400, 400))
|
||||
import sys
|
||||
for filename in sys.argv:
|
||||
if ".gcode" in filename:
|
||||
|
@ -985,8 +985,8 @@ def main():
|
|||
#TODO: add stl here
|
||||
pass
|
||||
|
||||
#frame = wx.Frame(None, -1, "GL Window", size=(400, 400))
|
||||
#panel = TestGlPanel(frame, size=(300,300))
|
||||
#frame = wx.Frame(None, -1, "GL Window", size = (400, 400))
|
||||
#panel = TestGlPanel(frame, size = (300, 300))
|
||||
frame.Show(True)
|
||||
app.MainLoop()
|
||||
app.Destroy()
|
||||
|
|
|
@ -22,8 +22,8 @@ from bufferedcanvas import *
|
|||
class Graph(BufferedCanvas):
|
||||
'''A class to show a Graph with Pronterface.'''
|
||||
|
||||
def __init__(self, parent, id, pos=wx.DefaultPosition,
|
||||
size=wx.DefaultSize, style=0):
|
||||
def __init__(self, parent, id, pos = wx.DefaultPosition,
|
||||
size = wx.DefaultSize, style = 0):
|
||||
# Forcing a no full repaint to stop flickering
|
||||
style = style | wx.NO_FULL_REPAINT_ON_RESIZE
|
||||
#call super function
|
||||
|
@ -53,7 +53,7 @@ class Graph(BufferedCanvas):
|
|||
|
||||
|
||||
#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)
|
||||
|
||||
|
||||
|
@ -78,23 +78,23 @@ class Graph(BufferedCanvas):
|
|||
|
||||
|
||||
def drawgrid(self, dc, gc):
|
||||
#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)
|
||||
#col2 = wx.Colour(255,255,255, 128)
|
||||
#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)
|
||||
#col2 = wx.Colour(255, 255, 255, 128)
|
||||
|
||||
#b = gc.CreateLinearGradientBrush(0, 0, w, h, col1, col2)
|
||||
|
||||
gc.SetPen(wx.Pen(wx.Colour(255,0,0,0), 4))
|
||||
#gc.SetBrush(gc.CreateBrush(wx.Brush(wx.Colour(245,245,255,252))))
|
||||
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(b)
|
||||
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.SetPen(wx.Pen(wx.Colour(255,0,0,0), 4))
|
||||
#gc.SetBrush(gc.CreateBrush(wx.Brush(wx.Colour(0, 0, 0, 255))))
|
||||
#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.MoveToPoint(0.0, 0.0)
|
||||
|
@ -107,34 +107,34 @@ class Graph(BufferedCanvas):
|
|||
|
||||
|
||||
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):
|
||||
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):
|
||||
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))
|
||||
|
||||
if self.timer.IsRunning() == False:
|
||||
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))
|
||||
|
||||
#dc.DrawCircle(50,50, 1)
|
||||
#dc.DrawCircle(50, 50, 1)
|
||||
|
||||
#gc.SetPen(wx.Pen(wx.Colour(255,0,0,0), 1))
|
||||
#gc.DrawLines([[20,30], [10,53]])
|
||||
#dc.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]])
|
||||
#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):
|
||||
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:
|
||||
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_pos = float(0.0)
|
||||
|
@ -143,7 +143,7 @@ class Graph(BufferedCanvas):
|
|||
for temperature in (temperature_list):
|
||||
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.
|
||||
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
|
||||
x_pos = float(x_pos) + x_add
|
||||
|
@ -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.NORMAL)
|
||||
if self.timer.IsRunning() == False:
|
||||
gc.SetFont(font, wx.Colour(128,128,128))
|
||||
gc.SetFont(font, wx.Colour(128, 128, 128))
|
||||
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, 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):
|
|||
|
||||
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
|
@ -263,5 +263,3 @@ class Graph(BufferedCanvas):
|
|||
self.drawextruder0temp(dc, gc)
|
||||
self.drawextruder1targettemp(dc, gc)
|
||||
self.drawextruder1temp(dc, gc)
|
||||
|
||||
|
||||
|
|
377
printrun/gviz.py
377
printrun/gviz.py
|
@ -1,273 +1,273 @@
|
|||
# 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,time
|
||||
import wx, time
|
||||
|
||||
from printrun_utils import imagefile
|
||||
|
||||
ID_ABOUT = 101
|
||||
ID_EXIT = 110
|
||||
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):
|
||||
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)
|
||||
|
||||
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]))
|
||||
self.p = gviz(self, size = size, build_dimensions = build_dimensions, grid = grid, extrusion_width = extrusion_width)
|
||||
|
||||
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(2, wx.Image(imagefile('zoom_out.png'), wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Zoom Out [-]', '')
|
||||
toolbar.AddSeparator()
|
||||
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(5, wx.EmptyBitmap(16,16), 'Reset view', '')
|
||||
toolbar.AddSimpleTool(5, wx.EmptyBitmap(16, 16), 'Reset view', '')
|
||||
toolbar.AddSeparator()
|
||||
#toolbar.AddSimpleTool(5, wx.Image('./images/inject.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap(), 'Insert Code at start of this layer', '')
|
||||
toolbar.Realize()
|
||||
vbox.Add(toolbar, 0, border=5)
|
||||
vbox.Add(toolbar, 0, border = 5)
|
||||
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/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.layerdown(), id=4)
|
||||
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.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.layerup(), id = 3)
|
||||
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, lambda x:self.p.inject(), id = 5)
|
||||
|
||||
|
||||
self.CreateStatusBar(1);
|
||||
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.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.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.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.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.bs = wx.Button(self.p, -1, "Inject", pos = (85, 103), size = (50, 20))
|
||||
|
||||
#self.bu.SetToolTip(wx.ToolTip("Move up one layer"))
|
||||
#self.bd.SetToolTip(wx.ToolTip("Move down one layer"))
|
||||
#self.bi.SetToolTip(wx.ToolTip("Zoom view in"))
|
||||
#self.bo.SetToolTip(wx.ToolTip("Zoom view out"))
|
||||
#self.bs.SetToolTip(wx.ToolTip("Insert Code at start of this layer"))
|
||||
|
||||
#self.bu.Bind(wx.EVT_BUTTON,lambda x:self.p.layerup())
|
||||
#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.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())
|
||||
|
||||
s=time.time()
|
||||
|
||||
#self.bu.Bind(wx.EVT_BUTTON, lambda x:self.p.layerup())
|
||||
#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.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())
|
||||
|
||||
s = time.time()
|
||||
#print time.time()-s
|
||||
self.initpos=[0,0]
|
||||
self.p.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.bi.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.p.Bind(wx.EVT_MOUSEWHEEL,self.zoom)
|
||||
self.Bind(wx.EVT_MOUSEWHEEL,self.zoom)
|
||||
self.p.Bind(wx.EVT_MOUSE_EVENTS,self.mouse)
|
||||
self.Bind(wx.EVT_MOUSE_EVENTS,self.mouse)
|
||||
|
||||
def resetview(self,event):
|
||||
self.p.translate=[0.0,0.0]
|
||||
self.p.scale=self.p.basescale
|
||||
self.p.zoom(0,0,1.0)
|
||||
|
||||
def mouse(self,event):
|
||||
self.initpos = [0, 0]
|
||||
self.p.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.bi.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.p.Bind(wx.EVT_MOUSEWHEEL, self.zoom)
|
||||
self.Bind(wx.EVT_MOUSEWHEEL, self.zoom)
|
||||
self.p.Bind(wx.EVT_MOUSE_EVENTS, self.mouse)
|
||||
self.Bind(wx.EVT_MOUSE_EVENTS, self.mouse)
|
||||
|
||||
def resetview(self, event):
|
||||
self.p.translate = [0.0, 0.0]
|
||||
self.p.scale = self.p.basescale
|
||||
self.p.zoom(0, 0, 1.0)
|
||||
|
||||
def mouse(self, event):
|
||||
if event.ButtonUp(wx.MOUSE_BTN_LEFT):
|
||||
if(self.initpos is not None):
|
||||
self.initpos=None
|
||||
self.initpos = None
|
||||
elif event.Dragging():
|
||||
e=event.GetPositionTuple()
|
||||
if self.initpos is None or not hasattr(self,"basetrans"):
|
||||
self.initpos=e
|
||||
self.basetrans=self.p.translate
|
||||
#print self.p.translate,e,self.initpos
|
||||
e = event.GetPositionTuple()
|
||||
if self.initpos is None or not hasattr(self, "basetrans"):
|
||||
self.initpos = e
|
||||
self.basetrans = self.p.translate
|
||||
#print self.p.translate, e, self.initpos
|
||||
self.p.translate = [ self.basetrans[0]+(e[0]-self.initpos[0]),
|
||||
self.basetrans[1]+(e[1]-self.initpos[1]) ]
|
||||
self.p.repaint()
|
||||
self.p.Refresh()
|
||||
|
||||
|
||||
else:
|
||||
event.Skip()
|
||||
|
||||
|
||||
def key(self, event):
|
||||
# Keycode definitions
|
||||
kup=[85, 315] # Up keys
|
||||
kdo=[68, 317] # Down Keys
|
||||
kzi=[388, 316, 61] # Zoom In Keys
|
||||
kzo=[390, 314, 45] # Zoom Out Keys
|
||||
x=event.GetKeyCode()
|
||||
kup = [85, 315] # Up keys
|
||||
kdo = [68, 317] # Down Keys
|
||||
kzi = [388, 316, 61] # Zoom In Keys
|
||||
kzo = [390, 314, 45] # Zoom Out Keys
|
||||
x = event.GetKeyCode()
|
||||
#print "Key event - "+str(x)
|
||||
#if event.ShiftDown():
|
||||
cx,cy=self.p.translate
|
||||
# if x==wx.WXK_UP:
|
||||
# self.p.zoom(cx,cy,1.2)
|
||||
# if x==wx.WXK_DOWN:
|
||||
# self.p.zoom(cx,cy,1/1.2)
|
||||
cx, cy = self.p.translate
|
||||
# if x == wx.WXK_UP:
|
||||
# self.p.zoom(cx, cy, 1.2)
|
||||
# if x == wx.WXK_DOWN:
|
||||
# self.p.zoom(cx, cy, 1/1.2)
|
||||
#else:
|
||||
# if x==wx.WXK_UP:
|
||||
# if x == wx.WXK_UP:
|
||||
# self.p.layerup()
|
||||
# if x==wx.WXK_DOWN:
|
||||
# if x == wx.WXK_DOWN:
|
||||
# self.p.layerdown()
|
||||
if x in kup:
|
||||
self.p.layerup()
|
||||
if x in kdo:
|
||||
self.p.layerdown()
|
||||
if x in kzi:
|
||||
self.p.zoom(cx,cy,1.2)
|
||||
self.p.zoom(cx, cy, 1.2)
|
||||
if x in kzo:
|
||||
self.p.zoom(cx, cy, 1/1.2)
|
||||
|
||||
|
||||
#print p.lines.keys()
|
||||
def zoom(self, event):
|
||||
z=event.GetWheelRotation()
|
||||
z = event.GetWheelRotation()
|
||||
if event.ShiftDown():
|
||||
if z > 0: self.p.layerdown()
|
||||
elif z < 0: self.p.layerup()
|
||||
else:
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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):
|
||||
wx.Panel.__init__(self,parent,-1,size=(size[0],size[1]))
|
||||
self.parent=parent
|
||||
self.size=size
|
||||
self.build_dimensions=build_dimensions
|
||||
self.grid=grid
|
||||
self.lastpos=[0,0,0,0,0,0,0]
|
||||
self.hilightpos=self.lastpos[:]
|
||||
self.Bind(wx.EVT_PAINT,self.paint)
|
||||
self.Bind(wx.EVT_SIZE,self.resize)
|
||||
self.lines={}
|
||||
self.pens={}
|
||||
self.arcs={}
|
||||
self.arcpens={}
|
||||
self.layers=[]
|
||||
self.layerindex=0
|
||||
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.scale=self.basescale
|
||||
penwidth = max(1.0,self.filament_width*((self.scale[0]+self.scale[1])/2.0))
|
||||
self.translate=[0.0,0.0]
|
||||
self.mainpen=wx.Pen(wx.Colour(0,0,0),penwidth)
|
||||
self.arcpen=wx.Pen(wx.Colour(255,0,0),penwidth)
|
||||
self.travelpen=wx.Pen(wx.Colour(10,80,80),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.penslist=[self.mainpen,self.travelpen,self.hlpen]+self.fades
|
||||
self.showall=0
|
||||
self.hilight=[]
|
||||
self.hilightarcs=[]
|
||||
self.dirty=1
|
||||
self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1)
|
||||
|
||||
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]))
|
||||
self.parent = parent
|
||||
self.size = size
|
||||
self.build_dimensions = build_dimensions
|
||||
self.grid = grid
|
||||
self.lastpos = [0, 0, 0, 0, 0, 0, 0]
|
||||
self.hilightpos = self.lastpos[:]
|
||||
self.Bind(wx.EVT_PAINT, self.paint)
|
||||
self.Bind(wx.EVT_SIZE, self.resize)
|
||||
self.lines = {}
|
||||
self.pens = {}
|
||||
self.arcs = {}
|
||||
self.arcpens = {}
|
||||
self.layers = []
|
||||
self.layerindex = 0
|
||||
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.scale = self.basescale
|
||||
penwidth = max(1.0, self.filament_width*((self.scale[0]+self.scale[1])/2.0))
|
||||
self.translate = [0.0, 0.0]
|
||||
self.mainpen = wx.Pen(wx.Colour(0, 0, 0), penwidth)
|
||||
self.arcpen = wx.Pen(wx.Colour(255, 0, 0), penwidth)
|
||||
self.travelpen = wx.Pen(wx.Colour(10, 80, 80), 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.penslist = [self.mainpen, self.travelpen, self.hlpen]+self.fades
|
||||
self.showall = 0
|
||||
self.hilight = []
|
||||
self.hilightarcs = []
|
||||
self.dirty = 1
|
||||
self.blitmap = wx.EmptyBitmap(self.GetClientSize()[0], self.GetClientSize()[1],-1)
|
||||
|
||||
def inject(self):
|
||||
#import pdb; pdb.set_trace()
|
||||
print"Inject code here..."
|
||||
print "Layer "+str(self.layerindex +1)+" - Z = "+str(self.layers[self.layerindex])+" mm"
|
||||
|
||||
|
||||
def clear(self):
|
||||
self.lastpos=[0,0,0,0,0,0,0]
|
||||
self.lines={}
|
||||
self.pens={}
|
||||
self.arcs={}
|
||||
self.arcpens={}
|
||||
self.layers=[]
|
||||
self.hilight=[]
|
||||
self.hilightarcs=[]
|
||||
self.layerindex=0
|
||||
self.showall=0
|
||||
self.dirty=1
|
||||
#self.repaint()
|
||||
self.lastpos = [0, 0, 0, 0, 0, 0, 0]
|
||||
self.lines = {}
|
||||
self.pens = {}
|
||||
self.arcs = {}
|
||||
self.arcpens = {}
|
||||
self.layers = []
|
||||
self.hilight = []
|
||||
self.hilightarcs = []
|
||||
self.layerindex = 0
|
||||
self.showall = 0
|
||||
self.dirty = 1
|
||||
#self.repaint()
|
||||
def layerup(self):
|
||||
if(self.layerindex+1<len(self.layers)):
|
||||
self.layerindex+=1
|
||||
# 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.Refresh()
|
||||
|
||||
|
||||
def layerdown(self):
|
||||
if(self.layerindex>0):
|
||||
self.layerindex-=1
|
||||
self.layerindex-=1
|
||||
# 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.Refresh()
|
||||
|
||||
def setlayer(self,layer):
|
||||
|
||||
def setlayer(self, layer):
|
||||
try:
|
||||
self.layerindex=self.layers.index(layer)
|
||||
self.layerindex = self.layers.index(layer)
|
||||
self.repaint()
|
||||
wx.CallAfter(self.Refresh)
|
||||
self.showall=0
|
||||
self.showall = 0
|
||||
except:
|
||||
pass
|
||||
|
||||
def resize(self,event):
|
||||
size=self.GetClientSize()
|
||||
newsize=min(float(size[0])/self.size[0],float(size[1])/self.size[1])
|
||||
self.size=self.GetClientSize()
|
||||
wx.CallAfter(self.zoom,0,0,newsize)
|
||||
|
||||
|
||||
def zoom(self,x,y,factor):
|
||||
def resize(self, event):
|
||||
size = self.GetClientSize()
|
||||
newsize = min(float(size[0])/self.size[0], float(size[1])/self.size[1])
|
||||
self.size = self.GetClientSize()
|
||||
wx.CallAfter(self.zoom, 0, 0, newsize)
|
||||
|
||||
|
||||
def zoom(self, x, y, factor):
|
||||
self.scale = [s * factor for s in self.scale]
|
||||
|
||||
|
||||
self.translate = [ x - (x-self.translate[0]) * 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:
|
||||
pen.SetWidth(penwidth)
|
||||
#self.dirty=1
|
||||
#self.dirty = 1
|
||||
self.repaint()
|
||||
self.Refresh()
|
||||
|
||||
|
||||
|
||||
|
||||
def repaint(self):
|
||||
self.blitmap=wx.EmptyBitmap(self.GetClientSize()[0],self.GetClientSize()[1],-1)
|
||||
dc=wx.MemoryDC()
|
||||
self.blitmap = wx.EmptyBitmap(self.GetClientSize()[0], self.GetClientSize()[1],-1)
|
||||
dc = wx.MemoryDC()
|
||||
dc.SelectObject(self.blitmap)
|
||||
dc.SetBackground(wx.Brush((250,250,200)))
|
||||
dc.SetBackground(wx.Brush((250, 250, 200)))
|
||||
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:
|
||||
if grid_unit > 0:
|
||||
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):
|
||||
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.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)))
|
||||
if not self.showall:
|
||||
self.size = self.GetSize()
|
||||
dc.SetBrush(wx.Brush((43,144,255)))
|
||||
dc.DrawRectangle(self.size[0]-15,0,15,self.size[1])
|
||||
dc.SetBrush(wx.Brush((0,255,0)))
|
||||
dc.SetBrush(wx.Brush((43, 144, 255)))
|
||||
dc.DrawRectangle(self.size[0]-15, 0, 15, self.size[1])
|
||||
dc.SetBrush(wx.Brush((0, 255, 0)))
|
||||
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)
|
||||
|
||||
def _drawlines(lines,pens):
|
||||
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 _scaler(x):
|
||||
return (self.scale[0]*x[0]+self.translate[0],
|
||||
self.scale[1]*x[1]+self.translate[1],
|
||||
self.scale[0]*x[2]+self.translate[0],
|
||||
self.scale[1]*x[3]+self.translate[1],)
|
||||
scaled_lines = map(_scaler,lines)
|
||||
scaled_lines = map(_scaler, lines)
|
||||
dc.DrawLineList(scaled_lines, pens)
|
||||
|
||||
def _drawarcs(arcs,pens):
|
||||
|
||||
def _drawarcs(arcs, pens):
|
||||
def _scaler(x):
|
||||
return (self.scale[0]*x[0]+self.translate[0],
|
||||
self.scale[1]*x[1]+self.translate[1],
|
||||
|
@ -275,61 +275,61 @@ class gviz(wx.Panel):
|
|||
self.scale[1]*x[3]+self.translate[1],
|
||||
self.scale[0]*x[4]+self.translate[0],
|
||||
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)):
|
||||
dc.SetPen(pens[i] if type(pens).__name__ == 'list' else pens)
|
||||
dc.SetBrush(wx.TRANSPARENT_BRUSH)
|
||||
dc.DrawArc(*scaled_arcs[i])
|
||||
|
||||
|
||||
if self.showall:
|
||||
l=[]
|
||||
l = []
|
||||
for i in self.layers:
|
||||
dc.DrawLineList(l,self.fades[0])
|
||||
dc.DrawLineList(l, self.fades[0])
|
||||
_drawlines(self.lines[i], self.pens[i])
|
||||
_drawarcs(self.arcs[i], self.arcpens[i])
|
||||
return
|
||||
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
|
||||
_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])
|
||||
_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]])
|
||||
|
||||
|
||||
_drawlines(self.hilight, self.hlpen)
|
||||
_drawarcs(self.hilightarcs, self.hlpen)
|
||||
|
||||
|
||||
dc.SelectObject(wx.NullBitmap)
|
||||
|
||||
def paint(self,event):
|
||||
dc=wx.PaintDC(self)
|
||||
|
||||
def paint(self, event):
|
||||
dc = wx.PaintDC(self)
|
||||
if(self.dirty):
|
||||
self.repaint()
|
||||
self.dirty=0
|
||||
sz=self.GetClientSize()
|
||||
dc.DrawBitmap(self.blitmap,0,0)
|
||||
self.dirty = 0
|
||||
sz = self.GetClientSize()
|
||||
dc.DrawBitmap(self.blitmap, 0, 0)
|
||||
del dc
|
||||
|
||||
def addfile(self,gcodes=[]):
|
||||
|
||||
def addfile(self, gcodes = []):
|
||||
self.clear()
|
||||
for i in gcodes:
|
||||
self.addgcode(i)
|
||||
|
||||
def addgcode(self,gcode="M105",hilight=0):
|
||||
gcode=gcode.split("*")[0]
|
||||
gcode=gcode.split(";")[0]
|
||||
|
||||
def addgcode(self, gcode = "M105", hilight = 0):
|
||||
gcode = gcode.split("*")[0]
|
||||
gcode = gcode.split(";")[0]
|
||||
gcode = gcode.lower().strip().split()
|
||||
if len(gcode) == 0:
|
||||
return
|
||||
if gcode[0][0] == 'n':
|
||||
gcode.pop(0)
|
||||
|
||||
|
||||
def _readgcode():
|
||||
target=self.lastpos[:]
|
||||
target = self.lastpos[:]
|
||||
target[5]=0.0
|
||||
target[6]=0.0
|
||||
if hilight:
|
||||
target=self.hilightpos[:]
|
||||
target = self.hilightpos[:]
|
||||
for i in gcode:
|
||||
if i[0]=="x":
|
||||
target[0]=float(i[1:])
|
||||
|
@ -353,14 +353,14 @@ class gviz(wx.Panel):
|
|||
self.arcpens[target[2]]=[]
|
||||
self.layers+=[target[2]]
|
||||
return target
|
||||
|
||||
|
||||
def _y(y):
|
||||
return self.build_dimensions[1]-(y-self.build_dimensions[4])
|
||||
def _x(x):
|
||||
return x-self.build_dimensions[3]
|
||||
|
||||
|
||||
start_pos = self.hilightpos[:] if hilight else self.lastpos[:]
|
||||
|
||||
|
||||
if gcode[0] in [ "g0", "g1" ]:
|
||||
target = _readgcode()
|
||||
line = [ _x(start_pos[0]), _y(start_pos[1]), _x(target[0]), _y(target[1]) ]
|
||||
|
@ -372,7 +372,7 @@ class gviz(wx.Panel):
|
|||
self.hilight += [line]
|
||||
self.hilightpos = target
|
||||
self.dirty = 1
|
||||
|
||||
|
||||
if gcode[0] in [ "g2", "g3" ]:
|
||||
target = _readgcode()
|
||||
arc = []
|
||||
|
@ -381,7 +381,7 @@ class gviz(wx.Panel):
|
|||
arc += [ _x(start_pos[0] + target[5]), _y(start_pos[1] + target[6]) ] # center
|
||||
if gcode[0] == "g2": # clockwise, reverse endpoints
|
||||
arc[0], arc[1], arc[2], arc[3] = arc[2], arc[3], arc[0], arc[1]
|
||||
|
||||
|
||||
if not hilight:
|
||||
self.arcs[ target[2] ] += [arc]
|
||||
self.arcpens[ target[2] ] += [self.arcpen]
|
||||
|
@ -390,11 +390,10 @@ class gviz(wx.Panel):
|
|||
self.hilightarcs += [arc]
|
||||
self.hilightpos = target
|
||||
self.dirty = 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = wx.App(False)
|
||||
#main = window(open("/home/kliment/designs/spinner/arm_export.gcode"))
|
||||
main = window(open("jam.gcode"))
|
||||
main.Show()
|
||||
app.MainLoop()
|
||||
|
||||
|
|
|
@ -1,371 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# 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/>.
|
||||
|
||||
from serial import Serial, SerialException
|
||||
from threading import Thread
|
||||
from select import error as SelectError
|
||||
import time, getopt, sys
|
||||
|
||||
class printcore():
|
||||
def __init__(self,port=None,baud=None):
|
||||
"""Initializes a printcore instance. Pass the port and baud rate to connect immediately
|
||||
"""
|
||||
self.baud=None
|
||||
self.port=None
|
||||
self.printer=None #Serial instance connected to the printer, None when disconnected
|
||||
self.clear=0 #clear to send, enabled after responses
|
||||
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.mainqueue=[]
|
||||
self.priqueue=[]
|
||||
self.queueindex=0
|
||||
self.lineno=0
|
||||
self.resendfrom=-1
|
||||
self.paused=False
|
||||
self.sentlines={}
|
||||
self.log=[]
|
||||
self.sent=[]
|
||||
self.tempcb=None#impl (wholeline)
|
||||
self.recvcb=None#impl (wholeline)
|
||||
self.sendcb=None#impl (wholeline)
|
||||
self.errorcb=None#impl (wholeline)
|
||||
self.startcb=None#impl ()
|
||||
self.endcb=None#impl ()
|
||||
self.onlinecb=None#impl ()
|
||||
self.loud=False#emit sent and received lines to terminal
|
||||
self.greetings=['start','Grbl ']
|
||||
self.wait=0# default wait period for send(), send_now()
|
||||
if port is not None and baud is not None:
|
||||
#print port, baud
|
||||
self.connect(port, baud)
|
||||
#print "connected\n"
|
||||
|
||||
|
||||
def disconnect(self):
|
||||
"""Disconnects from printer and pauses the print
|
||||
"""
|
||||
if(self.printer):
|
||||
self.printer.close()
|
||||
self.printer=None
|
||||
self.online=False
|
||||
self.printing=False
|
||||
|
||||
def connect(self,port=None,baud=None):
|
||||
"""Set port and baudrate if given, then connect to printer
|
||||
"""
|
||||
if(self.printer):
|
||||
self.disconnect()
|
||||
if port is not None:
|
||||
self.port=port
|
||||
if baud is not None:
|
||||
self.baud=baud
|
||||
if self.port is not None and self.baud is not None:
|
||||
self.printer=Serial(self.port,self.baud,timeout=5)
|
||||
Thread(target=self._listen).start()
|
||||
|
||||
def reset(self):
|
||||
"""Reset the printer
|
||||
"""
|
||||
if(self.printer):
|
||||
self.printer.setDTR(1)
|
||||
self.printer.setDTR(0)
|
||||
|
||||
|
||||
def _listen(self):
|
||||
"""This function acts on messages from the firmware
|
||||
"""
|
||||
self.clear=True
|
||||
time.sleep(1.0)
|
||||
if (not self.online and not self.printing):
|
||||
self._send("M105")
|
||||
while(True):
|
||||
if(not self.printer or not self.printer.isOpen):
|
||||
break
|
||||
try:
|
||||
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
|
||||
if(line.startswith(tuple(self.greetings)) or line.startswith('ok')):
|
||||
self.clear=True
|
||||
if(line.startswith(tuple(self.greetings)) or line.startswith('ok') or "T:" in line):
|
||||
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
|
||||
elif(line.startswith('Error')):
|
||||
if self.errorcb is not None:
|
||||
try:
|
||||
self.errorcb(line)
|
||||
except:
|
||||
pass
|
||||
#callback for errors
|
||||
pass
|
||||
# Teststrings for resend parsing # Firmware exp. result
|
||||
# line="rs N2 Expected checksum 67" # Teacup 2
|
||||
if line.lower().startswith("resend") or line.startswith("rs"):
|
||||
line=line.replace("N:"," ").replace("N"," ").replace(":"," ")
|
||||
linewords=line.split()
|
||||
while len(linewords) != 0:
|
||||
try:
|
||||
toresend=int(linewords.pop(0))
|
||||
self.resendfrom=toresend
|
||||
#print str(toresend)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
self.clear=True
|
||||
self.clear=True
|
||||
#callback for disconnect
|
||||
|
||||
def _checksum(self,command):
|
||||
return reduce(lambda x,y:x^y, map(ord,command))
|
||||
|
||||
def startprint(self,data):
|
||||
"""Start a print, data is an array of gcode commands.
|
||||
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.
|
||||
Printing will then start in a parallel thread.
|
||||
"""
|
||||
if(self.printing or not self.online or not self.printer):
|
||||
return False
|
||||
self.printing=True
|
||||
self.mainqueue=[]+data
|
||||
self.lineno=0
|
||||
self.queueindex=0
|
||||
self.resendfrom=-1
|
||||
self._send("M110",-1, True)
|
||||
if len(data)==0:
|
||||
return True
|
||||
self.clear=False
|
||||
Thread(target=self._print).start()
|
||||
return True
|
||||
|
||||
def pause(self):
|
||||
"""Pauses the print, saving the current position.
|
||||
"""
|
||||
self.paused=True
|
||||
self.printing=False
|
||||
time.sleep(1)
|
||||
|
||||
def resume(self):
|
||||
"""Resumes a paused print.
|
||||
"""
|
||||
self.paused=False
|
||||
self.printing=True
|
||||
Thread(target=self._print).start()
|
||||
|
||||
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
|
||||
"""
|
||||
|
||||
if(self.online):
|
||||
if(self.printing):
|
||||
self.mainqueue+=[command]
|
||||
else:
|
||||
while not self.clear:
|
||||
time.sleep(0.001)
|
||||
if (wait == 0 and self.wait > 0):
|
||||
wait = self.wait
|
||||
if (wait > 0):
|
||||
self.clear=False
|
||||
self._send(command,self.lineno,True)
|
||||
self.lineno+=1
|
||||
while ((wait > 0) and not self.clear):
|
||||
time.sleep(0.001)
|
||||
wait-=1
|
||||
else:
|
||||
print "Not connected to printer."
|
||||
|
||||
|
||||
def send_now(self,command,wait=0):
|
||||
"""Sends a command to the printer ahead of the command queue, without a checksum
|
||||
"""
|
||||
if(self.online or force):
|
||||
if(self.printing):
|
||||
self.priqueue+=[command]
|
||||
else:
|
||||
while not self.clear:
|
||||
time.sleep(0.001)
|
||||
if (wait == 0 and self.wait > 0):
|
||||
wait = self.wait
|
||||
if (wait > 0):
|
||||
self.clear=False
|
||||
self._send(command)
|
||||
while ((wait > 0) and not self.clear):
|
||||
time.sleep(0.001)
|
||||
wait-=1
|
||||
#callback for command sent
|
||||
else:
|
||||
print "Not connected to printer."
|
||||
|
||||
def _print(self):
|
||||
#callback for printing started
|
||||
if self.startcb is not None:
|
||||
try:
|
||||
self.startcb()
|
||||
except:
|
||||
pass
|
||||
while(self.printing and self.printer and self.online):
|
||||
self._sendnext()
|
||||
self.sentlines={}
|
||||
self.log=[]
|
||||
self.sent=[]
|
||||
if self.endcb is not None:
|
||||
try:
|
||||
self.endcb()
|
||||
except:
|
||||
pass
|
||||
#callback for printing done
|
||||
|
||||
def _sendnext(self):
|
||||
if(not self.printer):
|
||||
return
|
||||
while not self.clear:
|
||||
time.sleep(0.001)
|
||||
self.clear=False
|
||||
if not (self.printing and self.printer and self.online):
|
||||
self.clear=True
|
||||
return
|
||||
if(self.resendfrom<self.lineno and self.resendfrom>-1):
|
||||
self._send(self.sentlines[self.resendfrom],self.resendfrom,False)
|
||||
self.resendfrom+=1
|
||||
return
|
||||
self.resendfrom=-1
|
||||
for i in self.priqueue[:]:
|
||||
self._send(i)
|
||||
del(self.priqueue[0])
|
||||
return
|
||||
if(self.printing and self.queueindex<len(self.mainqueue)):
|
||||
tline=self.mainqueue[self.queueindex]
|
||||
tline=tline.split(";")[0]
|
||||
if(len(tline)>0):
|
||||
self._send(tline,self.lineno,True)
|
||||
self.lineno+=1
|
||||
else:
|
||||
self.clear=True
|
||||
self.queueindex+=1
|
||||
else:
|
||||
self.printing=False
|
||||
self.clear=True
|
||||
if(not self.paused):
|
||||
self.queueindex=0
|
||||
self.lineno=0
|
||||
self._send("M110",-1, True)
|
||||
|
||||
def _send(self, command, lineno=0, calcchecksum=False):
|
||||
if(calcchecksum):
|
||||
prefix="N"+str(lineno)+" "+command
|
||||
command=prefix+"*"+str(self._checksum(prefix))
|
||||
if("M110" not in command):
|
||||
self.sentlines[lineno]=command
|
||||
if(self.printer):
|
||||
self.sent+=[command]
|
||||
if self.loud:
|
||||
print "SENT: ",command
|
||||
if self.sendcb is not None:
|
||||
try:
|
||||
self.sendcb(command)
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
self.printer.write(str(command+"\n"))
|
||||
except SerialException, e:
|
||||
print "Can't write to printer (disconnected?)."
|
||||
|
||||
if __name__ == '__main__':
|
||||
baud = 115200
|
||||
loud = False
|
||||
statusreport=False
|
||||
try:
|
||||
opts, args=getopt.getopt(sys.argv[1:], "h,b:,v,s",["help","baud","verbose","statusreport"])
|
||||
except getopt.GetoptError,err:
|
||||
print str(err)
|
||||
print help
|
||||
sys.exit(2)
|
||||
for o,a in opts:
|
||||
if o in ('-h', '--help'):
|
||||
# FIXME: Fix help
|
||||
print "Opts are: --help , -b --baud = baudrate, -v --verbose, -s --statusreport"
|
||||
sys.exit(1)
|
||||
if o in ('-b', '--baud'):
|
||||
baud = int(a)
|
||||
if o in ('-v','--verbose'):
|
||||
loud=True
|
||||
elif o in ('-s','--statusreport'):
|
||||
statusreport=True
|
||||
|
||||
|
||||
if len(args)>1:
|
||||
port=args[-2]
|
||||
filename=args[-1]
|
||||
print "Printing: "+filename + " on "+port + " with baudrate "+str(baud)
|
||||
else:
|
||||
print "Usage: python [-h|-b|-v|-s] printcore.py /dev/tty[USB|ACM]x filename.gcode"
|
||||
sys.exit(2)
|
||||
p=printcore(port,baud)
|
||||
p.loud = loud
|
||||
time.sleep(2)
|
||||
gcode=[i.replace("\n","") for i in open(filename)]
|
||||
p.startprint(gcode)
|
||||
|
||||
try:
|
||||
if statusreport:
|
||||
p.loud=False
|
||||
sys.stdout.write("Progress: 00.0%")
|
||||
sys.stdout.flush()
|
||||
while(p.printing):
|
||||
time.sleep(1)
|
||||
if statusreport:
|
||||
sys.stdout.write("\b\b\b\b%02.1f%%" % (100*float(p.queueindex)/len(p.mainqueue),) )
|
||||
sys.stdout.flush()
|
||||
p.disconnect()
|
||||
sys.exit(0)
|
||||
except:
|
||||
p.disconnect()
|
|
@ -1,19 +1,21 @@
|
|||
import os
|
||||
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):
|
||||
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'):
|
||||
gettext.install(domain, '/usr/local/share/pronterface/locale', unicode=1)
|
||||
else:
|
||||
gettext.install(domain, './locale', unicode=1)
|
||||
gettext.install(domain, '/usr/local/share/pronterface/locale', unicode = 1)
|
||||
else:
|
||||
gettext.install(domain, './locale', unicode = 1)
|
||||
|
||||
def imagefile(filename):
|
||||
for prefix in ['/usr/local/share/pronterface/images', '/usr/share/pronterface/images']:
|
||||
candidate = os.path.join(prefix, filename)
|
||||
if os.path.exists(candidate):
|
||||
return candidate
|
||||
candidate = os.path.join(prefix, filename)
|
||||
if os.path.exists(candidate):
|
||||
return candidate
|
||||
local_candidate = os.path.join(os.path.dirname(__file__), "images", filename)
|
||||
if os.path.exists(local_candidate):
|
||||
return local_candidate
|
||||
|
@ -22,9 +24,9 @@ def imagefile(filename):
|
|||
|
||||
def lookup_file(filename, prefixes):
|
||||
for prefix in prefixes:
|
||||
candidate = os.path.join(prefix, filename)
|
||||
if os.path.exists(candidate):
|
||||
return candidate
|
||||
candidate = os.path.join(prefix, filename)
|
||||
if os.path.exists(candidate):
|
||||
return candidate
|
||||
return filename
|
||||
|
||||
def pixmapfile(filename):
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
# 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/>.
|
||||
|
||||
|
@ -21,10 +21,10 @@ import tempfile
|
|||
import shutil
|
||||
import svg.document as wxpsvgdocument
|
||||
import imghdr
|
||||
|
||||
|
||||
class dispframe(wx.Frame):
|
||||
def __init__(self, parent, title, res=(800, 600), printer=None):
|
||||
wx.Frame.__init__(self, parent=parent, title=title)
|
||||
def __init__(self, parent, title, res = (800, 600), printer = None):
|
||||
wx.Frame.__init__(self, parent = parent, title = title)
|
||||
self.p = printer
|
||||
self.pic = wx.StaticBitmap(self)
|
||||
self.bitmap = wx.EmptyBitmap(*res)
|
||||
|
@ -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")]
|
||||
dc.DrawPolygon(points, self.size[0] / 2, self.size[1] / 2)
|
||||
elif self.slicer == 'Slic3r':
|
||||
gc = wx.GraphicsContext_Create(dc)
|
||||
gc = wx.GraphicsContext_Create(dc)
|
||||
gc.Translate(*self.offset)
|
||||
gc.Scale(self.scale, self.scale)
|
||||
wxpsvgdocument.SVGDocument(image).render(gc)
|
||||
|
@ -69,12 +69,12 @@ class dispframe(wx.Frame):
|
|||
self.pic.SetBitmap(self.bitmap)
|
||||
self.pic.Show()
|
||||
self.Refresh()
|
||||
|
||||
|
||||
|
||||
|
||||
except:
|
||||
raise
|
||||
pass
|
||||
|
||||
|
||||
def showimgdelay(self, image):
|
||||
self.drawlayer(image)
|
||||
self.pic.Show()
|
||||
|
@ -82,10 +82,10 @@ class dispframe(wx.Frame):
|
|||
|
||||
self.Refresh()
|
||||
if self.p != None and self.p.online:
|
||||
self.p.send_now("G91")
|
||||
self.p.send_now("G1 Z%f F300" % (self.thickness,))
|
||||
self.p.send_now("G90")
|
||||
|
||||
self.p.send_now("G91")
|
||||
self.p.send_now("G1 Z%f F300" % (self.thickness,))
|
||||
self.p.send_now("G90")
|
||||
|
||||
def nextimg(self, event):
|
||||
if self.index < len(self.layers):
|
||||
i = self.index
|
||||
|
@ -99,9 +99,9 @@ class dispframe(wx.Frame):
|
|||
wx.CallAfter(self.pic.Hide)
|
||||
wx.CallAfter(self.Refresh)
|
||||
wx.CallAfter(self.ShowFullScreen, 0)
|
||||
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)):
|
||||
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)):
|
||||
wx.CallAfter(self.pic.Hide)
|
||||
wx.CallAfter(self.Refresh)
|
||||
self.layers = layers
|
||||
|
@ -117,58 +117,58 @@ class dispframe(wx.Frame):
|
|||
self.timer.Start(1000 * interval + 1000 * pause)
|
||||
|
||||
class setframe(wx.Frame):
|
||||
|
||||
def __init__(self, parent, printer=None):
|
||||
wx.Frame.__init__(self, parent, title="Projector setup")
|
||||
self.f = dispframe(None, "", printer=printer)
|
||||
|
||||
def __init__(self, parent, printer = None):
|
||||
wx.Frame.__init__(self, parent, title = "Projector setup")
|
||||
self.f = dispframe(None, "", printer = printer)
|
||||
self.panel = wx.Panel(self)
|
||||
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)
|
||||
|
||||
wx.StaticText(self.panel, -1, "Layer:", pos=(0, 30))
|
||||
wx.StaticText(self.panel, -1, "mm", pos=(130, 30))
|
||||
self.thickness = wx.TextCtrl(self.panel, -1, "0.5", pos=(50, 30))
|
||||
wx.StaticText(self.panel, -1, "Layer:", pos = (0, 30))
|
||||
wx.StaticText(self.panel, -1, "mm", pos = (130, 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, "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, "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, "Scale:", pos=(0, 120))
|
||||
wx.StaticText(self.panel, -1, "x", pos=(130, 120))
|
||||
self.scale = wx.TextCtrl(self.panel, -1, "5", pos=(50, 120))
|
||||
wx.StaticText(self.panel, -1, "Scale:", pos = (0, 120))
|
||||
wx.StaticText(self.panel, -1, "x", pos = (130, 120))
|
||||
self.scale = wx.TextCtrl(self.panel, -1, "5", pos = (50, 120))
|
||||
|
||||
wx.StaticText(self.panel, -1, "X:", pos=(160, 30))
|
||||
self.X = wx.TextCtrl(self.panel, -1, "1024", pos=(210, 30))
|
||||
wx.StaticText(self.panel, -1, "X:", pos = (160, 30))
|
||||
self.X = wx.TextCtrl(self.panel, -1, "1024", pos = (210, 30))
|
||||
|
||||
wx.StaticText(self.panel, -1, "Y:", pos=(160, 60))
|
||||
self.Y = wx.TextCtrl(self.panel, -1, "768", pos=(210, 60))
|
||||
|
||||
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, "Y:", pos = (160, 60))
|
||||
self.Y = wx.TextCtrl(self.panel, -1, "768", pos = (210, 60))
|
||||
|
||||
wx.StaticText(self.panel, -1, "OffsetY:", pos=(160, 120))
|
||||
self.offsetY = wx.TextCtrl(self.panel, -1, "50", pos=(210, 120))
|
||||
|
||||
self.bload = wx.Button(self.panel, -1, "Present", pos=(0, 150))
|
||||
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.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)
|
||||
|
||||
wx.StaticText(self.panel, -1, "Fullscreen:", pos=(160, 150))
|
||||
self.fullscreen = wx.CheckBox(self.panel, -1, pos=(220, 150))
|
||||
|
||||
wx.StaticText(self.panel, -1, "Fullscreen:", pos = (160, 150))
|
||||
self.fullscreen = wx.CheckBox(self.panel, -1, pos = (220, 150))
|
||||
self.fullscreen.SetValue(True)
|
||||
|
||||
|
||||
self.Show()
|
||||
|
||||
def __del__(self):
|
||||
if hasattr(self, 'image_dir') and self.image_dir != '':
|
||||
shutil.rmtree(self.image_dir)
|
||||
|
||||
|
||||
def parsesvg(self, name):
|
||||
et = xml.etree.ElementTree.ElementTree(file=name)
|
||||
et = xml.etree.ElementTree.ElementTree(file = name)
|
||||
#xml.etree.ElementTree.dump(et)
|
||||
slicer = 'Slic3r' if et.getroot().find('{http://www.w3.org/2000/svg}metadata') == None else 'Skeinforge'
|
||||
zlast = 0
|
||||
|
@ -177,18 +177,18 @@ class setframe(wx.Frame):
|
|||
if (slicer == 'Slic3r'):
|
||||
height = et.getroot().get('height')
|
||||
width = et.getroot().get('width')
|
||||
|
||||
|
||||
for i in et.findall("{http://www.w3.org/2000/svg}g"):
|
||||
z = float(i.get('{http://slic3r.org/namespaces/slic3r}z'))
|
||||
zdiff = z - zlast
|
||||
zlast = z
|
||||
|
||||
|
||||
svgSnippet = xml.etree.ElementTree.Element('{http://www.w3.org/2000/svg}svg')
|
||||
svgSnippet.set('height', height + 'mm')
|
||||
svgSnippet.set('width', width + 'mm')
|
||||
svgSnippet.set('viewBox', '0 0 ' + height + ' ' + width)
|
||||
svgSnippet.append(i)
|
||||
|
||||
|
||||
ol += [svgSnippet]
|
||||
else :
|
||||
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):
|
|||
path = i.find('{http://www.w3.org/2000/svg}path')
|
||||
ol += [(path.get("d").split("z"))[:-1]]
|
||||
return ol, zdiff, slicer
|
||||
|
||||
|
||||
def parse3DLPzip(self, name):
|
||||
if not zipfile.is_zipfile(name):
|
||||
raise Exception(name + " is not a zip file!")
|
||||
|
@ -212,9 +212,9 @@ class setframe(wx.Frame):
|
|||
if os.path.isfile(path) and imghdr.what(path) in acceptedImageTypes:
|
||||
ol.append(wx.Bitmap(path))
|
||||
return ol, -1, "bitmap"
|
||||
|
||||
|
||||
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;)"))
|
||||
if(dlg.ShowModal() == wx.ID_OK):
|
||||
name = dlg.GetPath()
|
||||
|
@ -240,12 +240,12 @@ class setframe(wx.Frame):
|
|||
self.f.ShowFullScreen(1)
|
||||
l = self.layers[0][:]
|
||||
self.f.present(l,
|
||||
thickness=float(self.thickness.GetValue()),
|
||||
interval=float(self.interval.GetValue()),
|
||||
scale=float(self.scale.GetValue()),
|
||||
pause=float(self.delay.GetValue()),
|
||||
size=(float(self.X.GetValue()), float(self.Y.GetValue())),
|
||||
offset=(float(self.offsetX.GetValue()), float(self.offsetY.GetValue())))
|
||||
thickness = float(self.thickness.GetValue()),
|
||||
interval = float(self.interval.GetValue()),
|
||||
scale = float(self.scale.GetValue()),
|
||||
pause = float(self.delay.GetValue()),
|
||||
size = (float(self.X.GetValue()), float(self.Y.GetValue())),
|
||||
offset = (float(self.offsetX.GetValue()), float(self.offsetY.GetValue())))
|
||||
|
||||
if __name__ == "__main__":
|
||||
a = wx.App()
|
||||
|
|
|
@ -0,0 +1,317 @@
|
|||
# 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)
|
|
@ -1,70 +1,70 @@
|
|||
# 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 sys, struct, math
|
||||
|
||||
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]]
|
||||
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]]
|
||||
|
||||
def genfacet(v):
|
||||
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]]
|
||||
vecx=cross(veca,vecb)
|
||||
vlen=math.sqrt(sum(map(lambda x:x*x,vecx)))
|
||||
if vlen==0:
|
||||
vlen=1
|
||||
normal=map(lambda x:x/vlen, vecx)
|
||||
return [normal,v]
|
||||
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]]
|
||||
vecx = cross(veca, vecb)
|
||||
vlen = math.sqrt(sum(map(lambda x:x*x, vecx)))
|
||||
if vlen == 0:
|
||||
vlen = 1
|
||||
normal = map(lambda x:x/vlen, vecx)
|
||||
return [normal, v]
|
||||
|
||||
I=[
|
||||
[1,0,0,0],
|
||||
[0,1,0,0],
|
||||
[0,0,1,0],
|
||||
[0,0,0,1]
|
||||
I = [
|
||||
[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 1]
|
||||
]
|
||||
|
||||
def transpose(matrix):
|
||||
return zip(*matrix)
|
||||
#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)))))
|
||||
|
||||
def applymatrix(facet,matrix=I):
|
||||
|
||||
def applymatrix(facet, matrix = I):
|
||||
#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 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]]]
|
||||
m=[
|
||||
[1,0,0,0],
|
||||
[0,1,0,0],
|
||||
[0,0,1,1],
|
||||
[0,0,0,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]))
|
||||
|
||||
f = [[0, 0, 0],[[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565],[-3.022642, 0.642482, -9.510565]]]
|
||||
m = [
|
||||
[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 1, 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:
|
||||
return
|
||||
if binary:
|
||||
f=open(filename,"wb")
|
||||
buf="".join(["\0"]*80)
|
||||
buf+=struct.pack("<I",len(facets))
|
||||
facetformat=struct.Struct("<ffffffffffffH")
|
||||
f = open(filename, "wb")
|
||||
buf = "".join(["\0"]*80)
|
||||
buf+=struct.pack("<I", len(facets))
|
||||
facetformat = struct.Struct("<ffffffffffffH")
|
||||
for i in facets:
|
||||
l=list(i[0][:])
|
||||
l = list(i[0][:])
|
||||
for j in i[1]:
|
||||
l+=j[:]
|
||||
l+=[0]
|
||||
|
@ -73,167 +73,167 @@ def emitstl(filename,facets=[],objname="stltool_export",binary=1):
|
|||
f.write(buf)
|
||||
f.close()
|
||||
return
|
||||
|
||||
|
||||
f=open(filename,"w")
|
||||
|
||||
f = open(filename, "w")
|
||||
f.write("solid "+objname+"\n")
|
||||
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]:
|
||||
f.write(" vertex "+" ".join(map(str,j))+"\n")
|
||||
f.write(" vertex "+" ".join(map(str, j))+"\n")
|
||||
f.write(" endloop"+"\n")
|
||||
f.write(" endfacet"+"\n")
|
||||
f.write("endsolid "+objname+"\n")
|
||||
f.close()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class stl:
|
||||
def __init__(self, filename=None):
|
||||
self.facet=[[0,0,0],[[0,0,0],[0,0,0],[0,0,0]]]
|
||||
self.facets=[]
|
||||
self.facetsminz=[]
|
||||
self.facetsmaxz=[]
|
||||
|
||||
self.name=""
|
||||
self.insolid=0
|
||||
self.infacet=0
|
||||
self.inloop=0
|
||||
self.facetloc=0
|
||||
def __init__(self, filename = None):
|
||||
self.facet = [[0, 0, 0],[[0, 0, 0],[0, 0, 0],[0, 0, 0]]]
|
||||
self.facets = []
|
||||
self.facetsminz = []
|
||||
self.facetsmaxz = []
|
||||
|
||||
self.name = ""
|
||||
self.insolid = 0
|
||||
self.infacet = 0
|
||||
self.inloop = 0
|
||||
self.facetloc = 0
|
||||
if filename is None:
|
||||
return
|
||||
self.f=list(open(filename))
|
||||
self.f = list(open(filename))
|
||||
if not self.f[0].startswith("solid"):
|
||||
print "Not an ascii stl solid - attempting to parse as binary"
|
||||
f=open(filename,"rb")
|
||||
buf=f.read(84)
|
||||
f = open(filename, "rb")
|
||||
buf = f.read(84)
|
||||
while(len(buf)<84):
|
||||
newdata=f.read(84-len(buf))
|
||||
newdata = f.read(84-len(buf))
|
||||
if not len(newdata):
|
||||
break
|
||||
buf+=newdata
|
||||
facetcount=struct.unpack_from("<I",buf,80)
|
||||
facetformat=struct.Struct("<ffffffffffffH")
|
||||
facetcount = struct.unpack_from("<I", buf, 80)
|
||||
facetformat = struct.Struct("<ffffffffffffH")
|
||||
for i in xrange(facetcount[0]):
|
||||
buf=f.read(50)
|
||||
buf = f.read(50)
|
||||
while(len(buf)<50):
|
||||
newdata=f.read(50-len(buf))
|
||||
newdata = f.read(50-len(buf))
|
||||
if not len(newdata):
|
||||
break
|
||||
buf+=newdata
|
||||
fd=list(facetformat.unpack(buf))
|
||||
self.name="binary soloid"
|
||||
self.facet=[fd[:3],[fd[3:6],fd[6:9],fd[9:12]]]
|
||||
fd = list(facetformat.unpack(buf))
|
||||
self.name = "binary soloid"
|
||||
self.facet = [fd[:3],[fd[3:6], fd[6:9], fd[9:12]]]
|
||||
self.facets+=[self.facet]
|
||||
facet=self.facet
|
||||
self.facetsminz+=[(min(map(lambda x:x[2], facet[1])),facet)]
|
||||
self.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])),facet)]
|
||||
facet = self.facet
|
||||
self.facetsminz+=[(min(map(lambda x:x[2], facet[1])), facet)]
|
||||
self.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])), facet)]
|
||||
f.close()
|
||||
return
|
||||
for i in self.f:
|
||||
if not self.parseline(i):
|
||||
return
|
||||
|
||||
def translate(self,v=[0,0,0]):
|
||||
matrix=[
|
||||
[1,0,0,v[0]],
|
||||
[0,1,0,v[1]],
|
||||
[0,0,1,v[2]],
|
||||
[0,0,0,1]
|
||||
|
||||
def translate(self, v = [0, 0, 0]):
|
||||
matrix = [
|
||||
[1, 0, 0, v[0]],
|
||||
[0, 1, 0, v[1]],
|
||||
[0, 0, 1, v[2]],
|
||||
[0, 0, 0, 1]
|
||||
]
|
||||
return self.transform(matrix)
|
||||
|
||||
def rotate(self,v=[0,0,0]):
|
||||
|
||||
def rotate(self, v = [0, 0, 0]):
|
||||
import math
|
||||
z=v[2]
|
||||
matrix1=[
|
||||
[math.cos(math.radians(z)),-math.sin(math.radians(z)),0,0],
|
||||
[math.sin(math.radians(z)),math.cos(math.radians(z)),0,0],
|
||||
[0,0,1,0],
|
||||
[0,0,0,1]
|
||||
z = v[2]
|
||||
matrix1 = [
|
||||
[math.cos(math.radians(z)),-math.sin(math.radians(z)), 0, 0],
|
||||
[math.sin(math.radians(z)), math.cos(math.radians(z)), 0, 0],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 1]
|
||||
]
|
||||
y=v[0]
|
||||
matrix2=[
|
||||
[1,0,0,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,0,0,1]
|
||||
y = v[0]
|
||||
matrix2 = [
|
||||
[1, 0, 0, 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, 0, 0, 1]
|
||||
]
|
||||
x=v[1]
|
||||
matrix3=[
|
||||
[math.cos(math.radians(x)),0,-math.sin(math.radians(x)),0],
|
||||
[0,1,0,0],
|
||||
[math.sin(math.radians(x)),0,math.cos(math.radians(x)),0],
|
||||
[0,0,0,1]
|
||||
x = v[1]
|
||||
matrix3 = [
|
||||
[math.cos(math.radians(x)), 0,-math.sin(math.radians(x)), 0],
|
||||
[0, 1, 0, 0],
|
||||
[math.sin(math.radians(x)), 0, math.cos(math.radians(x)), 0],
|
||||
[0, 0, 0, 1]
|
||||
]
|
||||
return self.transform(matrix1).transform(matrix2).transform(matrix3)
|
||||
|
||||
def scale(self,v=[0,0,0]):
|
||||
matrix=[
|
||||
[v[0],0,0,0],
|
||||
[0,v[1],0,0],
|
||||
[0,0,v[2],0],
|
||||
[0,0,0,1]
|
||||
|
||||
def scale(self, v = [0, 0, 0]):
|
||||
matrix = [
|
||||
[v[0], 0, 0, 0],
|
||||
[0, v[1], 0, 0],
|
||||
[0, 0, v[2], 0],
|
||||
[0, 0, 0, 1]
|
||||
]
|
||||
return self.transform(matrix)
|
||||
|
||||
|
||||
def transform(self,m=I):
|
||||
s=stl()
|
||||
s.facets=[applymatrix(i,m) for i in self.facets]
|
||||
s.insolid=0
|
||||
s.infacet=0
|
||||
s.inloop=0
|
||||
s.facetloc=0
|
||||
s.name=self.name
|
||||
|
||||
|
||||
def transform(self, m = I):
|
||||
s = stl()
|
||||
s.facets = [applymatrix(i, m) for i in self.facets]
|
||||
s.insolid = 0
|
||||
s.infacet = 0
|
||||
s.inloop = 0
|
||||
s.facetloc = 0
|
||||
s.name = self.name
|
||||
for facet in s.facets:
|
||||
s.facetsminz+=[(min(map(lambda x:x[2], facet[1])),facet)]
|
||||
s.facetsmaxz+=[(max(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)]
|
||||
return s
|
||||
|
||||
def export(self,f=sys.stdout):
|
||||
|
||||
def export(self, f = sys.stdout):
|
||||
f.write("solid "+self.name+"\n")
|
||||
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")
|
||||
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(" endfacet"+"\n")
|
||||
f.write("endsolid "+self.name+"\n")
|
||||
f.flush()
|
||||
|
||||
def parseline(self,l):
|
||||
l=l.strip()
|
||||
|
||||
def parseline(self, l):
|
||||
l = l.strip()
|
||||
if l.startswith("solid"):
|
||||
self.insolid=1
|
||||
self.name=l[6:]
|
||||
self.insolid = 1
|
||||
self.name = l[6:]
|
||||
#print self.name
|
||||
|
||||
|
||||
elif l.startswith("endsolid"):
|
||||
self.insolid=0
|
||||
self.insolid = 0
|
||||
return 0
|
||||
elif l.startswith("facet normal"):
|
||||
l=l.replace(",",".")
|
||||
self.infacet=11
|
||||
self.facetloc=0
|
||||
self.facet=[[0,0,0],[[0,0,0],[0,0,0],[0,0,0]]]
|
||||
self.facet[0]=map(float,l.split()[2:])
|
||||
l = l.replace(", ",".")
|
||||
self.infacet = 11
|
||||
self.facetloc = 0
|
||||
self.facet = [[0, 0, 0],[[0, 0, 0],[0, 0, 0],[0, 0, 0]]]
|
||||
self.facet[0]=map(float, l.split()[2:])
|
||||
elif l.startswith("endfacet"):
|
||||
self.infacet=0
|
||||
self.infacet = 0
|
||||
self.facets+=[self.facet]
|
||||
facet=self.facet
|
||||
self.facetsminz+=[(min(map(lambda x:x[2], facet[1])),facet)]
|
||||
self.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])),facet)]
|
||||
facet = self.facet
|
||||
self.facetsminz+=[(min(map(lambda x:x[2], facet[1])), facet)]
|
||||
self.facetsmaxz+=[(max(map(lambda x:x[2], facet[1])), facet)]
|
||||
elif l.startswith("vertex"):
|
||||
l=l.replace(",",".")
|
||||
self.facet[1][self.facetloc]=map(float,l.split()[1:])
|
||||
l = l.replace(", ",".")
|
||||
self.facet[1][self.facetloc]=map(float, l.split()[1:])
|
||||
self.facetloc+=1
|
||||
return 1
|
||||
if __name__=="__main__":
|
||||
s=stl("../../Downloads/frame-vertex-neo-foot-x4.stl")
|
||||
for i in xrange(11,11):
|
||||
working=s.facets[:]
|
||||
if __name__ == "__main__":
|
||||
s = stl("../../Downloads/frame-vertex-neo-foot-x4.stl")
|
||||
for i in xrange(11, 11):
|
||||
working = s.facets[:]
|
||||
for j in reversed(sorted(s.facetsminz)):
|
||||
if(j[0]>i):
|
||||
working.remove(j[1])
|
||||
|
@ -244,7 +244,7 @@ if __name__=="__main__":
|
|||
working.remove(j[1])
|
||||
else:
|
||||
break
|
||||
|
||||
print i,len(working)
|
||||
emitstl("../../Downloads/frame-vertex-neo-foot-x4-a.stl",s.facets,"emitted_object")
|
||||
|
||||
print i, len(working)
|
||||
emitstl("../../Downloads/frame-vertex-neo-foot-x4-a.stl", s.facets, "emitted_object")
|
||||
#stl("../prusamendel/stl/mendelplate.stl")
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# 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/>.
|
||||
|
||||
|
@ -32,8 +32,8 @@ from pyglet.gl import *
|
|||
class GLPanel(wx.Panel):
|
||||
'''A simple class for using OpenGL with wxPython.'''
|
||||
|
||||
def __init__(self, parent, id, pos=wx.DefaultPosition,
|
||||
size=wx.DefaultSize, style=0):
|
||||
def __init__(self, parent, id, pos = wx.DefaultPosition,
|
||||
size = wx.DefaultSize, style = 0):
|
||||
# Forcing a no full repaint to stop flickering
|
||||
style = style | wx.NO_FULL_REPAINT_ON_RESIZE
|
||||
#call super function
|
||||
|
@ -46,7 +46,7 @@ class GLPanel(wx.Panel):
|
|||
glcanvas.WX_GL_DEPTH_SIZE, 24) # 24 bit
|
||||
# Create the canvas
|
||||
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.SetSizer(self.sizer)
|
||||
#self.sizer.Fit(self)
|
||||
|
@ -215,7 +215,7 @@ class stlview(object):
|
|||
normals.extend(i[0])
|
||||
|
||||
# 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]
|
||||
self.vertex_list = batch.add_indexed(len(vertices) // 3,
|
||||
GL_TRIANGLES,
|
||||
|
@ -233,7 +233,7 @@ def vdiff(v, o):
|
|||
|
||||
|
||||
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.
|
||||
vertices = []
|
||||
normals = []
|
||||
|
@ -258,7 +258,7 @@ class gcview(object):
|
|||
if lasth is not None:
|
||||
self.layers[lasth] = pyglet.graphics.Batch()
|
||||
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,
|
||||
GL_TRIANGLES,
|
||||
None, # group,
|
||||
|
@ -296,7 +296,7 @@ class gcview(object):
|
|||
t0 = time.time()
|
||||
|
||||
# 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,
|
||||
GL_TRIANGLES,
|
||||
None, # group,
|
||||
|
@ -304,14 +304,14 @@ class gcview(object):
|
|||
('v3f/static', vertices),
|
||||
('n3f/static', normals)))
|
||||
if lasth is not None:
|
||||
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))]
|
||||
self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3,
|
||||
GL_TRIANGLES,
|
||||
None, # group,
|
||||
indices,
|
||||
('v3f/static', layertemp[lasth][0]),
|
||||
('n3f/static', layertemp[lasth][1])))
|
||||
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))]
|
||||
self.vlists.append(self.layers[lasth].add_indexed(len(layertemp[lasth][0]) // 3,
|
||||
GL_TRIANGLES,
|
||||
None, # group,
|
||||
indices,
|
||||
('v3f/static', layertemp[lasth][0]),
|
||||
('n3f/static', layertemp[lasth][1])))
|
||||
|
||||
def genline(self, i, h, w):
|
||||
S = i[0][:3]
|
||||
|
@ -356,28 +356,28 @@ class gcview(object):
|
|||
return spoints, epoints, S, E
|
||||
|
||||
def transform(self, line):
|
||||
line = line.split(";")[0]
|
||||
cur = self.prev[:]
|
||||
if len(line) > 0:
|
||||
if "G1" in line or "G0" in line or "G92" in line:
|
||||
if("X" in line):
|
||||
cur[0] = float(line.split("X")[1].split(" ")[0])
|
||||
if("Y" in line):
|
||||
cur[1] = float(line.split("Y")[1].split(" ")[0])
|
||||
if("Z" in line):
|
||||
cur[2] = float(line.split("Z")[1].split(" ")[0])
|
||||
if("E" in line):
|
||||
cur[3] = float(line.split("E")[1].split(" ")[0])
|
||||
if self.prev == cur:
|
||||
return None
|
||||
if self.fline or "G92" in line:
|
||||
self.prev = cur
|
||||
self.fline = 0
|
||||
return None
|
||||
else:
|
||||
r = [self.prev, cur]
|
||||
self.prev = cur
|
||||
return r
|
||||
line = line.split(";")[0]
|
||||
cur = self.prev[:]
|
||||
if len(line) > 0:
|
||||
if "G1" in line or "G0" in line or "G92" in line:
|
||||
if("X" in line):
|
||||
cur[0] = float(line.split("X")[1].split(" ")[0])
|
||||
if("Y" in line):
|
||||
cur[1] = float(line.split("Y")[1].split(" ")[0])
|
||||
if("Z" in line):
|
||||
cur[2] = float(line.split("Z")[1].split(" ")[0])
|
||||
if("E" in line):
|
||||
cur[3] = float(line.split("E")[1].split(" ")[0])
|
||||
if self.prev == cur:
|
||||
return None
|
||||
if self.fline or "G92" in line:
|
||||
self.prev = cur
|
||||
self.fline = 0
|
||||
return None
|
||||
else:
|
||||
r = [self.prev, cur]
|
||||
self.prev = cur
|
||||
return r
|
||||
|
||||
def delete(self):
|
||||
for i in self.vlists:
|
||||
|
@ -466,7 +466,7 @@ def mulquat(q1, rq):
|
|||
|
||||
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)
|
||||
self.batches = []
|
||||
self.rot = 0
|
||||
|
@ -495,7 +495,7 @@ class TestGlPanel(GLPanel):
|
|||
def forceresize(self):
|
||||
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
|
||||
|
||||
def move_shape(self, delta):
|
||||
|
@ -547,7 +547,7 @@ class TestGlPanel(GLPanel):
|
|||
p1y = -(float(p1[1]) - sz[1] / 2) / (sz[1] / 2)
|
||||
p2x = (float(p2[0]) - sz[0] / 2) / (sz[0] / 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)
|
||||
if self.rot:
|
||||
self.basequat = mulquat(self.basequat, quat)
|
||||
|
@ -570,27 +570,27 @@ class TestGlPanel(GLPanel):
|
|||
self.initpos = None
|
||||
|
||||
elif event.Dragging() and event.RightIsDown() and event.ShiftDown():
|
||||
if self.initpos is None:
|
||||
self.initpos = event.GetPositionTuple()
|
||||
else:
|
||||
p1 = self.initpos
|
||||
p2 = event.GetPositionTuple()
|
||||
sz = self.GetClientSize()
|
||||
p1 = list(p1)
|
||||
p2 = list(p2)
|
||||
p1[1] *= -1
|
||||
p2[1] *= -1
|
||||
if self.initpos is None:
|
||||
self.initpos = event.GetPositionTuple()
|
||||
else:
|
||||
p1 = self.initpos
|
||||
p2 = event.GetPositionTuple()
|
||||
sz = self.GetClientSize()
|
||||
p1 = list(p1)
|
||||
p2 = list(p2)
|
||||
p1[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()
|
||||
glTranslatef(self.transv[0], self.transv[1], 0)
|
||||
glTranslatef(0, 0, self.transv[2])
|
||||
if(self.rot):
|
||||
glMultMatrixd(build_rotmatrix(self.basequat))
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
|
||||
self.rot = 1
|
||||
self.initpos = None
|
||||
glLoadIdentity()
|
||||
glTranslatef(self.transv[0], self.transv[1], 0)
|
||||
glTranslatef(0, 0, self.transv[2])
|
||||
if(self.rot):
|
||||
glMultMatrixd(build_rotmatrix(self.basequat))
|
||||
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
|
||||
self.rot = 1
|
||||
self.initpos = None
|
||||
else:
|
||||
#mouse is moving without a button press
|
||||
p = event.GetPositionTuple()
|
||||
|
@ -710,7 +710,7 @@ class TestGlPanel(GLPanel):
|
|||
|
||||
def drawmodel(self, m, n):
|
||||
batch = pyglet.graphics.Batch()
|
||||
stl = stlview(m.facets, batch=batch)
|
||||
stl = stlview(m.facets, batch = batch)
|
||||
m.batch = batch
|
||||
m.animoffset = 300
|
||||
#print m
|
||||
|
@ -819,8 +819,8 @@ class TestGlPanel(GLPanel):
|
|||
class GCFrame(wx.Frame):
|
||||
'''A simple class for using OpenGL with wxPython.'''
|
||||
|
||||
def __init__(self, parent, ID, title, pos=wx.DefaultPosition,
|
||||
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
|
||||
def __init__(self, parent, ID, title, pos = wx.DefaultPosition,
|
||||
size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
|
||||
super(GCFrame, self).__init__(parent, ID, title, pos, (size[0] + 150, size[1]), style)
|
||||
|
||||
class d:
|
||||
|
@ -833,21 +833,21 @@ class GCFrame(wx.Frame):
|
|||
m.curlayer = 0.0
|
||||
m.scale = [1.0, 1.0, 1.0]
|
||||
m.batch = pyglet.graphics.Batch()
|
||||
m.gc = gcview([], batch=m.batch)
|
||||
m.gc = gcview([], batch = m.batch)
|
||||
self.models = {"": m}
|
||||
self.l = d()
|
||||
self.modelindex = 0
|
||||
self.GLPanel1 = TestGlPanel(self, size)
|
||||
|
||||
def addfile(self, gcode=[]):
|
||||
def addfile(self, gcode = []):
|
||||
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):
|
||||
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)
|
||||
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):
|
|||
|
||||
|
||||
def main():
|
||||
app = wx.App(redirect=False)
|
||||
frame = GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size=(400, 400))
|
||||
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.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)
|
||||
#frame.Show(True)
|
||||
#app.MainLoop()
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
import wx
|
||||
|
||||
def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False):
|
||||
""" Draws an arc of an ellipse within bounding rect (x,y,w,h)
|
||||
def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise = False):
|
||||
""" 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)"""
|
||||
|
||||
|
||||
if True:
|
||||
import warnings
|
||||
warnings.warn("elliptical arcs are not supported")
|
||||
|
@ -15,7 +15,7 @@ def AddEllipticalArc(self, x, y, w, h, startAngle, endAngle, clockwise=False):
|
|||
h = h/2.0
|
||||
self.AddArc(x+w, y+h, ((w+h)/2), startAngle, endAngle, clockwise)
|
||||
return
|
||||
else:
|
||||
else:
|
||||
#implement in terms of AddArc by applying a transformation matrix
|
||||
#Sigh this can't work, still need to patch wx to allow
|
||||
#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):
|
|||
#possibly be simulated by combining the current transform with option a.
|
||||
mtx = wx.GraphicsRenderer_GetDefaultRenderer().CreateMatrix()
|
||||
path = wx.GraphicsRenderer_GetDefaultRenderer().CreatePath()
|
||||
|
||||
|
||||
|
||||
mtx.Translate(x+(w/2.0), y+(h/2.0))
|
||||
mtx.Scale(w/2.0, y/2.0)
|
||||
|
||||
|
||||
path.AddArc(0, 0, 1, startAngle, endAngle, clockwise)
|
||||
path.Transform(mtx)
|
||||
self.AddPath(path)
|
||||
self.MoveToPoint(path.GetCurrentPoint())
|
||||
self.CloseSubpath()
|
||||
|
||||
|
||||
if not hasattr(wx.GraphicsPath, "AddEllipticalArc"):
|
||||
wx.GraphicsPath.AddEllipticalArc = AddEllipticalArc
|
||||
|
||||
del AddEllipticalArc
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
Parsers for specific attributes
|
||||
"""
|
||||
import urlparse
|
||||
from pyparsing import (Literal,
|
||||
from pyparsing import (Literal,
|
||||
Optional, oneOf, Group, StringEnd, Combine, Word, alphas, hexnums,
|
||||
CaselessLiteral, SkipTo
|
||||
)
|
||||
|
@ -21,23 +21,23 @@ def parsePossibleURL(t):
|
|||
colorDeclaration = none | currentColor | colourValue
|
||||
|
||||
urlEnd = (
|
||||
Literal(")").suppress() +
|
||||
Optional(Group(colorDeclaration), default=()) +
|
||||
Literal(")").suppress() +
|
||||
Optional(Group(colorDeclaration), default = ()) +
|
||||
StringEnd()
|
||||
)
|
||||
|
||||
url = (
|
||||
CaselessLiteral("URL")
|
||||
+
|
||||
+
|
||||
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.
|
||||
#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))
|
||||
#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
|
||||
#The fallback will be another (type, details) tuple as a parsed
|
||||
#colorDeclaration, but may be the empty tuple if it is not present
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
from pyparsing import Literal, Combine
|
||||
from .identifier import identifier
|
||||
|
||||
atkeyword = Combine(Literal("@") + identifier)
|
||||
atkeyword = Combine(Literal("@") + identifier)
|
||||
|
|
|
@ -5,4 +5,3 @@
|
|||
from pyparsing import nestedExpr
|
||||
|
||||
block = nestedExpr(opener="{", closer="}")
|
||||
|
||||
|
|
|
@ -21,31 +21,31 @@ comma = Literal(",").suppress()
|
|||
def clampColourByte(val):
|
||||
val = int(val)
|
||||
return min(max(0,val), 255)
|
||||
|
||||
|
||||
def clampColourPerc(val):
|
||||
val = float(val)
|
||||
return min(max(0,val), 100)
|
||||
|
||||
|
||||
def parseColorPerc(token):
|
||||
val = token[0]
|
||||
val = clampColourPerc(val)
|
||||
#normalize to bytes
|
||||
return int(255 * (val / 100.0))
|
||||
|
||||
|
||||
|
||||
colorByte = Optional(sign) + integerConstant.setParseAction(lambda t: clampColourByte(t[0]))
|
||||
colorPerc = number.setParseAction(parseColorPerc) + Literal("%").suppress()
|
||||
|
||||
rgb = (
|
||||
Literal("rgb(").setParseAction(lambda t: "RGB") +
|
||||
|
||||
Literal("rgb(").setParseAction(lambda t: "RGB") +
|
||||
|
||||
(
|
||||
#integer constants, ie 255,255,255
|
||||
Group(colorByte + comma + colorByte + comma + colorByte) ^
|
||||
#percentage values, ie 100%, 50%
|
||||
Group(colorPerc + comma + colorPerc + comma + colorPerc)
|
||||
)
|
||||
+
|
||||
+
|
||||
Literal(")").suppress() + StringEnd()
|
||||
)
|
||||
|
||||
|
@ -54,10 +54,10 @@ def parseShortHex(t):
|
|||
|
||||
|
||||
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) |
|
||||
Word(hexnums, exact=3).setParseAction(parseShortHex)
|
||||
Word(hexnums, exact=3).setParseAction(parseShortHex)
|
||||
) + StringEnd()
|
||||
)
|
||||
|
||||
|
@ -66,7 +66,7 @@ def parseNamedColour(t):
|
|||
return ["RGB", NamedColours[t[0].lower()]]
|
||||
except KeyError:
|
||||
return ["RGB", (0,0,0)]
|
||||
|
||||
|
||||
namedColour = Word(alphas).setParseAction(parseNamedColour)
|
||||
|
||||
|
||||
|
@ -246,7 +246,7 @@ NamedColours = {
|
|||
|
||||
def fillCSS2SystemColours():
|
||||
#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
|
||||
systemColors = {
|
||||
"ActiveBorder": wx.SYS_COLOUR_ACTIVEBORDER,
|
||||
|
@ -280,4 +280,4 @@ def fillCSS2SystemColours():
|
|||
NamedColours.update(
|
||||
#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()
|
||||
)
|
||||
)
|
||||
|
|
|
@ -10,7 +10,7 @@ class White(White):
|
|||
super(White, self).__init__(ws, min, max, exact)
|
||||
|
||||
escaped = (
|
||||
Literal("\\").suppress() +
|
||||
Literal("\\").suppress() +
|
||||
#chr(20)-chr(126) + chr(128)-unichr(sys.maxunicode)
|
||||
Regex(u"[\u0020-\u007e\u0080-\uffff]", re.IGNORECASE)
|
||||
)
|
||||
|
@ -18,7 +18,7 @@ escaped = (
|
|||
def convertToUnicode(t):
|
||||
return unichr(int(t[0], 16))
|
||||
hex_unicode = (
|
||||
Literal("\\").suppress() +
|
||||
Literal("\\").suppress() +
|
||||
Regex("[0-9a-f]{1,6}", re.IGNORECASE) +
|
||||
Optional(White(exact=1)).suppress()
|
||||
).setParseAction(convertToUnicode)
|
||||
|
@ -29,9 +29,9 @@ escape = hex_unicode | escaped
|
|||
#any unicode literal outside the 0-127 ascii range
|
||||
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
|
||||
|
||||
nmchar = Regex(u"[0-9A-Z-]", re.IGNORECASE) | nonascii | escape
|
||||
|
||||
identifier = Combine(nmstart + ZeroOrMore(nmchar))
|
||||
identifier = Combine(nmstart + ZeroOrMore(nmchar))
|
||||
|
|
|
@ -5,4 +5,4 @@ def inlineStyle(styleString):
|
|||
return {}
|
||||
styles = styleString.split(";")
|
||||
rv = dict(style.split(":") for style in styles if len(style) != 0)
|
||||
return rv
|
||||
return rv
|
||||
|
|
|
@ -48,4 +48,4 @@ transformList = delimitedList(Group(transform), delim=maybeComma)
|
|||
|
||||
if __name__ == '__main__':
|
||||
from tests.test_css import *
|
||||
unittest.main()
|
||||
unittest.main()
|
||||
|
|
|
@ -43,4 +43,4 @@ length = lengthValue + Optional(lengthUnit, default=None) + StringEnd()
|
|||
length.leaveWhitespace()
|
||||
|
||||
#set the parse action aftward so it doesn't "infect" the parsers that build on it
|
||||
number.setParseAction(asFloat)
|
||||
number.setParseAction(asFloat)
|
||||
|
|
|
@ -14,22 +14,22 @@ from svg.css.colour import colourValue
|
|||
from svg.css import values
|
||||
from attributes import paintValue
|
||||
|
||||
document = """<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
document = """<?xml version = "1.0" standalone = "no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="4cm" height="4cm" viewBox="0 0 400 400"
|
||||
xmlns="http://www.w3.org/2000/svg" version="1.1">
|
||||
<svg width = "4cm" height = "4cm" viewBox = "0 0 400 400"
|
||||
xmlns = "http://www.w3.org/2000/svg" version = "1.1">
|
||||
<title>Example triangle01- simple example of a 'path'</title>
|
||||
<desc>A path that draws a triangle</desc>
|
||||
<rect x="1" y="1" width="398" height="398"
|
||||
fill="none" stroke="blue" />
|
||||
<path d="M 100 100 L 300 100 L 200 300 z"
|
||||
fill="red" stroke="blue" stroke-width="3" />
|
||||
<rect x = "1" y = "1" width = "398" height = "398"
|
||||
fill = "none" stroke = "blue" />
|
||||
<path d = "M 100 100 L 300 100 L 200 300 z"
|
||||
fill = "red" stroke = "blue" stroke-width = "3" />
|
||||
</svg>"""
|
||||
|
||||
makePath = lambda: wx.GraphicsRenderer_GetDefaultRenderer().CreatePath()
|
||||
|
||||
def attrAsFloat(node, attr, defaultValue="0"):
|
||||
def attrAsFloat(node, attr, defaultValue = "0"):
|
||||
val = node.get(attr, defaultValue)
|
||||
#TODO: process stuff like "inherit" by walking back up the nodes
|
||||
#fast path optimization - if it's a valid float, don't
|
||||
|
@ -38,8 +38,8 @@ def attrAsFloat(node, attr, defaultValue="0"):
|
|||
return float(val)
|
||||
except ValueError:
|
||||
return valueToPixels(val)
|
||||
|
||||
def valueToPixels(val, defaultUnits="px"):
|
||||
|
||||
def valueToPixels(val, defaultUnits = "px"):
|
||||
#TODO manage default units
|
||||
from pyparsing import ParseException
|
||||
try:
|
||||
|
@ -67,7 +67,7 @@ def pathHandler(func):
|
|||
ops = self.generatePathOps(path)
|
||||
return path, ops
|
||||
return inner
|
||||
|
||||
|
||||
|
||||
class SVGDocument(object):
|
||||
lastControl = None
|
||||
|
@ -102,12 +102,12 @@ class SVGDocument(object):
|
|||
def state(self):
|
||||
""" Retrieve the current state, without popping"""
|
||||
return self.stateStack[-1]
|
||||
|
||||
|
||||
def processElement(self, element):
|
||||
""" Process one element of the XML tree.
|
||||
Returns the path representing the node,
|
||||
and an operation list for drawing the node.
|
||||
|
||||
|
||||
Parent nodes should return a path (for hittesting), but
|
||||
no draw operations
|
||||
"""
|
||||
|
@ -126,7 +126,7 @@ class SVGDocument(object):
|
|||
""" Returns an oplist for transformations.
|
||||
This applies to a node, not the current state because
|
||||
the transform stack is saved in the wxGraphicsContext.
|
||||
|
||||
|
||||
This oplist does *not* include the push/pop state commands
|
||||
"""
|
||||
ops = []
|
||||
|
@ -175,21 +175,21 @@ class SVGDocument(object):
|
|||
)
|
||||
if transform == 'skewX':
|
||||
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(
|
||||
(wx.GraphicsContext.ConcatTransform, (matrix,))
|
||||
)
|
||||
if transform == 'skewY':
|
||||
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(
|
||||
(wx.GraphicsContext.ConcatTransform, (matrix,))
|
||||
)
|
||||
return ops
|
||||
|
||||
|
||||
|
||||
|
||||
def addGroupToDocument(self, node):
|
||||
""" For parent elements: push on a state,
|
||||
then process all child elements
|
||||
|
@ -197,7 +197,7 @@ class SVGDocument(object):
|
|||
ops = [
|
||||
(wx.GraphicsContext.PushState, ())
|
||||
]
|
||||
|
||||
|
||||
path = makePath()
|
||||
ops.extend(self.createTransformOpsFromNode(node))
|
||||
for child in node.getchildren():
|
||||
|
@ -210,7 +210,7 @@ class SVGDocument(object):
|
|||
(wx.GraphicsContext.PopState, ())
|
||||
)
|
||||
return path, ops
|
||||
|
||||
|
||||
def getFontFromState(self):
|
||||
font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
||||
family = self.state.get("font-family")
|
||||
|
@ -227,11 +227,11 @@ class SVGDocument(object):
|
|||
else:
|
||||
font.SetPointSize(int(val))
|
||||
return font
|
||||
|
||||
|
||||
def addTextToDocument(self, node):
|
||||
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
|
||||
#rather than the top as with our API. This function
|
||||
#will measure and then re-orient the text as needed.
|
||||
|
@ -252,14 +252,14 @@ class SVGDocument(object):
|
|||
(DoDrawText, (text, x, y))
|
||||
]
|
||||
return None, ops
|
||||
|
||||
|
||||
@pathHandler
|
||||
def addRectToDocument(self, node, path):
|
||||
x, y, w, h = (attrAsFloat(node, attr) for attr in ['x', 'y', 'width', 'height'])
|
||||
rx = node.get('rx')
|
||||
ry = node.get('ry')
|
||||
if not (w and h):
|
||||
path.MoveToPoint(x,y) #keep the current point correct
|
||||
path.MoveToPoint(x, y) #keep the current point correct
|
||||
return
|
||||
if rx or ry:
|
||||
if rx and ry:
|
||||
|
@ -271,7 +271,7 @@ class SVGDocument(object):
|
|||
#value clamping as per spec section 9.2
|
||||
rx = min(rx, w/2)
|
||||
ry = min(ry, h/2)
|
||||
|
||||
|
||||
#origin
|
||||
path.MoveToPoint(x+rx, y)
|
||||
path.AddLineToPoint(x+w-rx, y)
|
||||
|
@ -315,12 +315,12 @@ class SVGDocument(object):
|
|||
path.AddRectangle(
|
||||
x, y, w, h
|
||||
)
|
||||
|
||||
|
||||
@pathHandler
|
||||
def addCircleToDocument(self, node, path):
|
||||
cx, cy, r = [attrAsFloat(node, attr) for attr in ('cx', 'cy', 'r')]
|
||||
path.AddCircle(cx, cy, r)
|
||||
|
||||
|
||||
@pathHandler
|
||||
def addEllipseToDocument(self, node, path):
|
||||
cx, cy, rx, ry = [float(node.get(attr, 0)) for attr in ('cx', 'cy', 'rx', 'ry')]
|
||||
|
@ -332,29 +332,29 @@ class SVGDocument(object):
|
|||
x = cx - rx
|
||||
y = cy - ry
|
||||
path.AddEllipse(x, y, rx*2, ry*2)
|
||||
|
||||
@pathHandler
|
||||
|
||||
@pathHandler
|
||||
def addLineToDocument(self, node, path):
|
||||
x1, y1, x2, y2 = [attrAsFloat(node, attr) for attr in ('x1', 'y1', 'x2', 'y2')]
|
||||
path.MoveToPoint(x1, y1)
|
||||
path.AddLineToPoint(x2, y2)
|
||||
|
||||
|
||||
@pathHandler
|
||||
def addPolyLineToDocument(self, node, path):
|
||||
#translate to pathdata and render that
|
||||
data = "M " + node.get("points")
|
||||
self.addPathDataToPath(data, path)
|
||||
|
||||
@pathHandler
|
||||
|
||||
@pathHandler
|
||||
def addPolygonToDocument(self, node, path):
|
||||
#translate to pathdata and render that
|
||||
data = "M " + node.get("points") + " Z"
|
||||
self.addPathDataToPath(data, path)
|
||||
|
||||
|
||||
@pathHandler
|
||||
def addPathDataToDocument(self, node, path):
|
||||
self.addPathDataToPath(node.get('d', ''), path)
|
||||
|
||||
|
||||
def addPathDataToPath(self, data, path):
|
||||
self.lastControl = None
|
||||
self.lastControlQ = None
|
||||
|
@ -364,7 +364,7 @@ class SVGDocument(object):
|
|||
form of (command, [list of arguments]).
|
||||
We translate that to [(command, args[0]), (command, args[1])]
|
||||
via a generator.
|
||||
|
||||
|
||||
M is special cased because its subsequent arguments
|
||||
become linetos.
|
||||
"""
|
||||
|
@ -388,10 +388,10 @@ class SVGDocument(object):
|
|||
#print "parsed in", time.time()-t
|
||||
for stroke in normalizeStrokes(parsed):
|
||||
self.addStrokeToPath(path, stroke)
|
||||
|
||||
|
||||
|
||||
|
||||
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"""
|
||||
ops = []
|
||||
brush = self.getBrushFromState(path)
|
||||
|
@ -414,7 +414,7 @@ class SVGDocument(object):
|
|||
(wx.GraphicsContext.StrokePath, (path,))
|
||||
)
|
||||
return ops
|
||||
|
||||
|
||||
def getPenFromState(self):
|
||||
pencolour = self.state.get('stroke', 'none')
|
||||
if pencolour == 'currentColor':
|
||||
|
@ -449,7 +449,7 @@ class SVGDocument(object):
|
|||
pen.SetJoin(joinmap.get(self.state.get('stroke-linejoin', None), wx.JOIN_MITER))
|
||||
return wx.GraphicsRenderer_GetDefaultRenderer().CreatePen(pen)
|
||||
|
||||
def getBrushFromState(self, path=None):
|
||||
def getBrushFromState(self, path = None):
|
||||
brushcolour = self.state.get('fill', 'black').strip()
|
||||
type, details = paintValue.parseString(brushcolour)
|
||||
if type == "URL":
|
||||
|
@ -465,51 +465,51 @@ class SVGDocument(object):
|
|||
box = path.GetBox()
|
||||
x, y, w, h = box.Get()
|
||||
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':
|
||||
box = path.GetBox()
|
||||
x, y, w, h = box.Get()
|
||||
#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)
|
||||
fx, fy = cx, cy
|
||||
return wx.GraphicsRenderer.GetDefaultRenderer().CreateRadialGradientBrush(
|
||||
cx,cy,
|
||||
fx,fy,
|
||||
(max(w,h))/2,
|
||||
wx.Colour(0,0,255,128), wx.RED
|
||||
cx, cy,
|
||||
fx, fy,
|
||||
(max(w, h))/2,
|
||||
wx.Colour(0, 0, 255, 128), wx.RED
|
||||
)
|
||||
else:
|
||||
#invlid gradient specified
|
||||
return wx.NullBrush
|
||||
r,g,b = 0,0,0
|
||||
r, g, b = 0, 0, 0
|
||||
if type == 'CURRENTCOLOR':
|
||||
type, details = paintValue.parseString(self.state.get('color', 'none'))
|
||||
if type == 'RGB':
|
||||
r,g,b = details
|
||||
r, g, b = details
|
||||
elif type == "NONE":
|
||||
return wx.NullBrush
|
||||
opacity = self.state.get('fill-opacity', self.state.get('opacity', '1'))
|
||||
opacity = float(opacity)
|
||||
opacity = min(max(opacity, 0.0), 1.0)
|
||||
a = 255 * opacity
|
||||
#using try/except block instead of
|
||||
#using try/except block instead of
|
||||
#just setdefault because the wxBrush and wxColour would
|
||||
#be created every time anyway in order to pass them,
|
||||
#defeating the purpose of the cache
|
||||
try:
|
||||
return SVGDocument.brushCache[(r,g,b,a)]
|
||||
return SVGDocument.brushCache[(r, g, b, a)]
|
||||
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):
|
||||
"""
|
||||
Resolve a URL and return an elementTree Element from it.
|
||||
|
||||
|
||||
Return None if unresolvable
|
||||
|
||||
|
||||
"""
|
||||
scheme, netloc, path, query, fragment = urlData
|
||||
if scheme == netloc == path == '':
|
||||
|
@ -524,15 +524,15 @@ class SVGDocument(object):
|
|||
return None
|
||||
else:
|
||||
return self.resolveRemoteURL(urlData)
|
||||
|
||||
|
||||
def resolveRemoteURL(self, url):
|
||||
return None
|
||||
|
||||
|
||||
def addStrokeToPath(self, path, stroke):
|
||||
""" Given a stroke from a path command
|
||||
(in the form (command, arguments)) create the path
|
||||
commands that represent it.
|
||||
|
||||
|
||||
TODO: break out into (yet another) class/module,
|
||||
especially so we can get O(1) dispatch on type?
|
||||
"""
|
||||
|
@ -564,17 +564,17 @@ class SVGDocument(object):
|
|||
)
|
||||
self.lastControl = control2
|
||||
path.AddCurveToPoint(
|
||||
control1,
|
||||
control2,
|
||||
control1,
|
||||
control2,
|
||||
endpoint
|
||||
)
|
||||
#~ cp = path.GetCurrentPoint()
|
||||
#~ path.AddCircle(c1x, c1y, 5)
|
||||
#~ path.AddCircle(c2x, c2y, 3)
|
||||
#~ path.AddCircle(x,y, 7)
|
||||
#~ path.AddCircle(x, y, 7)
|
||||
#~ path.MoveToPoint(cp)
|
||||
#~ print "C", control1, control2, endpoint
|
||||
|
||||
|
||||
elif type == 'S':
|
||||
#control2, endpoint = arg
|
||||
control2, endpoint = map(
|
||||
|
@ -584,15 +584,15 @@ class SVGDocument(object):
|
|||
control1 = reflectPoint(self.lastControl, path.GetCurrentPoint())
|
||||
else:
|
||||
control1 = path.GetCurrentPoint()
|
||||
#~ print "S", self.lastControl,":",control1, control2, endpoint
|
||||
#~ print "S", self.lastControl, ":", control1, control2, endpoint
|
||||
self.lastControl = control2
|
||||
path.AddCurveToPoint(
|
||||
control1,
|
||||
control2,
|
||||
control1,
|
||||
control2,
|
||||
endpoint
|
||||
)
|
||||
elif type == "Q":
|
||||
(cx, cy), (x,y) = map(normalizePoint, arg)
|
||||
(cx, cy), (x, y) = map(normalizePoint, arg)
|
||||
self.lastControlQ = (cx, cy)
|
||||
path.AddQuadCurveToPoint(cx, cy, x, y)
|
||||
elif type == "T":
|
||||
|
@ -603,50 +603,50 @@ class SVGDocument(object):
|
|||
cx, cy = path.GetCurrentPoint()
|
||||
self.lastControlQ = (cx, cy)
|
||||
path.AddQuadCurveToPoint(cx, cy, x, y)
|
||||
|
||||
|
||||
elif type == "V":
|
||||
_, y = normalizePoint((0, arg))
|
||||
x, _ = path.GetCurrentPoint()
|
||||
path.AddLineToPoint(x,y)
|
||||
|
||||
path.AddLineToPoint(x, y)
|
||||
|
||||
elif type == "H":
|
||||
x, _ = normalizePoint((arg, 0))
|
||||
_, y = path.GetCurrentPoint()
|
||||
path.AddLineToPoint(x,y)
|
||||
|
||||
path.AddLineToPoint(x, y)
|
||||
|
||||
elif type == "A":
|
||||
#wxGC currently only supports circular arcs,
|
||||
#not eliptical ones
|
||||
|
||||
|
||||
(
|
||||
(rx, ry), #radii of ellipse
|
||||
angle, #angle of rotation on the ellipse in degrees
|
||||
(fa, fs), #arc and stroke angle flags
|
||||
(x, y) #endpoint on the arc
|
||||
) = arg
|
||||
|
||||
x, y = normalizePoint((x,y))
|
||||
) = arg
|
||||
|
||||
x, y = normalizePoint((x, y))
|
||||
cx, cy = path.GetCurrentPoint()
|
||||
if (cx, cy) == (x, y):
|
||||
return #noop
|
||||
|
||||
|
||||
if (rx == 0 or ry == 0):
|
||||
#no radius is effectively a line
|
||||
path.AddLineToPoint(x,y)
|
||||
path.AddLineToPoint(x, y)
|
||||
return
|
||||
|
||||
|
||||
#find the center point for the ellipse
|
||||
#translation via the angle
|
||||
angle = angle % 360
|
||||
angle = math.radians(angle)
|
||||
|
||||
|
||||
#translated endpoint
|
||||
xPrime = math.cos(angle) * ((cx-x)/2)
|
||||
xPrime += math.sin(angle) * ((cx-x)/2)
|
||||
yPrime = -(math.sin(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) * (yPrime**2)) + ((ry**2)*(xPrime**2))
|
||||
temp = abs(temp)
|
||||
|
@ -659,7 +659,7 @@ class SVGDocument(object):
|
|||
cyPrime = temp * -((ry * xPrime) / rx)
|
||||
if fa == fs:
|
||||
cxPrime, cyPrime = -cxPrime, -cyPrime
|
||||
|
||||
|
||||
#reflect backwards now for the origin
|
||||
cnx = math.cos(angle) * cxPrime
|
||||
cnx += math.sin(angle) * cxPrime
|
||||
|
@ -667,27 +667,27 @@ class SVGDocument(object):
|
|||
cny += (math.cos(angle)) * cyPrime
|
||||
cnx += ((cx+x)/2.0)
|
||||
cny += ((cy+y)/2.0)
|
||||
|
||||
|
||||
#calculate the angle between the two endpoints
|
||||
lastArc = wx.Point2D(x-cnx, y-cny).GetVectorAngle()
|
||||
firstArc = wx.Point2D(cx-cnx, cy-cny).GetVectorAngle()
|
||||
lastArc = math.radians(lastArc)
|
||||
firstArc = math.radians(firstArc)
|
||||
|
||||
|
||||
|
||||
|
||||
#aargh buggines.
|
||||
#AddArc draws a straight line between
|
||||
#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
|
||||
#taking out the MoveToPoint fills correctly.
|
||||
path.AddEllipse(cnx-rx, cny-ry, rx*2, ry*2)
|
||||
path.MoveToPoint(x, y)
|
||||
#~ npath = makePath()
|
||||
#~ npath.AddEllipticalArc(cnx-rx, cny-ry, rx*2, ry*2, firstArc, lastArc, False)
|
||||
#~ npath.MoveToPoint(x,y)
|
||||
#~ npath.MoveToPoint(x, y)
|
||||
#~ path.AddPath(npath)
|
||||
|
||||
|
||||
elif type == 'Z':
|
||||
#~ Bugginess:
|
||||
#~ CloseSubpath() doesn't change the
|
||||
|
@ -699,17 +699,17 @@ class SVGDocument(object):
|
|||
#~ results
|
||||
#~ Manually closing the path *and* calling CloseSubpath() appears
|
||||
#~ to give correct results on win32
|
||||
|
||||
|
||||
pt = self.firstPoints.pop()
|
||||
path.AddLineToPoint(pt)
|
||||
path.CloseSubpath()
|
||||
|
||||
|
||||
def render(self, context):
|
||||
if not hasattr(self, "ops"):
|
||||
return
|
||||
for op, args in self.ops:
|
||||
op(context, *args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from tests.test_document import *
|
||||
unittest.main()
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
"""
|
||||
SVG path data parser
|
||||
|
||||
|
||||
|
||||
|
||||
Usage:
|
||||
steps = svg.parseString(pathdata)
|
||||
for command, arguments in steps:
|
||||
pass
|
||||
|
||||
|
||||
"""
|
||||
|
||||
from pyparsing import (ParserElement, Literal, Word, CaselessLiteral,
|
||||
from pyparsing import (ParserElement, Literal, Word, CaselessLiteral,
|
||||
Optional, Combine, Forward, ZeroOrMore, nums, oneOf, Group, ParseException, OneOrMore)
|
||||
|
||||
|
||||
#ParserElement.enablePackrat()
|
||||
|
||||
def Command(char):
|
||||
""" Case insensitive but case preserving"""
|
||||
return CaselessPreservingLiteral(char)
|
||||
|
||||
|
||||
def Arguments(token):
|
||||
return Group(token)
|
||||
|
||||
|
||||
|
||||
|
||||
class CaselessPreservingLiteral(CaselessLiteral):
|
||||
""" Like CaselessLiteral, but returns the match as found
|
||||
instead of as defined.
|
||||
"""
|
||||
def __init__( self, matchString ):
|
||||
super(CaselessPreservingLiteral,self).__init__( matchString.upper() )
|
||||
super(CaselessPreservingLiteral, self).__init__( matchString.upper() )
|
||||
self.name = "'%s'" % matchString
|
||||
self.errmsg = "Expected " + self.name
|
||||
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 ]
|
||||
if test.upper() == self.match:
|
||||
return loc+self.matchLen, test
|
||||
|
@ -40,8 +40,8 @@ class CaselessPreservingLiteral(CaselessLiteral):
|
|||
exc = self.myException
|
||||
exc.loc = loc
|
||||
exc.pstr = instring
|
||||
raise exc
|
||||
|
||||
raise exc
|
||||
|
||||
def Sequence(token):
|
||||
""" A sequence of the token"""
|
||||
return OneOrMore(token+maybeComma)
|
||||
|
@ -58,13 +58,13 @@ def convertToFloat(s, loc, toks):
|
|||
|
||||
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
|
||||
#float() function to clear out invalid values - loosely matching like this
|
||||
#speeds up parsing quite a lot
|
||||
floatingPointConstant = Combine(
|
||||
Optional(sign) +
|
||||
Optional(Word(nums)) +
|
||||
Optional(sign) +
|
||||
Optional(Word(nums)) +
|
||||
Optional(Literal(".") + Optional(Word(nums)))+
|
||||
Optional(exponent)
|
||||
)
|
||||
|
@ -75,7 +75,7 @@ number = floatingPointConstant
|
|||
|
||||
#same as FP constant but don't allow a - sign
|
||||
nonnegativeNumber = Combine(
|
||||
Optional(Word(nums)) +
|
||||
Optional(Word(nums)) +
|
||||
Optional(Literal(".") + Optional(Word(nums)))+
|
||||
Optional(exponent)
|
||||
)
|
||||
|
@ -117,10 +117,10 @@ ellipticalArcArgument = Group(
|
|||
arcRadius + maybeComma + #rx, ry
|
||||
number + maybeComma +#rotation
|
||||
arcFlags + #large-arc-flag, sweep-flag
|
||||
coordinatePair #(x,y)
|
||||
coordinatePair #(x, y)
|
||||
)
|
||||
|
||||
|
||||
|
||||
ellipticalArc = Group(Command("A") + Arguments(Sequence(ellipticalArcArgument)))
|
||||
|
||||
smoothQuadraticBezierCurveto = Group(Command("T") + Arguments(coordinatePairSequence))
|
||||
|
@ -155,39 +155,37 @@ def profile():
|
|||
p.disable()
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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"""
|
||||
|
||||
def ptest():
|
||||
svg.parseString(bpath)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
|
||||
#~ from tests.test_pathdata import *
|
||||
#~ unittest.main()
|
||||
profile()
|
||||
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ from printrun.printrun_utils import configfile, imagefile, sharedfile
|
|||
users = {}
|
||||
|
||||
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():
|
||||
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():
|
||||
return "</body></html>"
|
||||
|
||||
|
@ -24,47 +24,47 @@ def TReloadPage(action):
|
|||
|
||||
def clear_text(mypass):
|
||||
return mypass
|
||||
|
||||
|
||||
gPronterPtr = 0
|
||||
gWeblog = ""
|
||||
gLogRefresh =5
|
||||
class SettingsPage(object):
|
||||
def __init__(self):
|
||||
self.name="<div id='title'>Pronterface Settings</div>"
|
||||
self.name = "<div id='title'>Pronterface Settings</div>"
|
||||
|
||||
def index(self):
|
||||
pageText=PrintHeader()+self.name+PrintMenu()
|
||||
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>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 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>Filename</b></td><td>"+str(gPronterPtr.filename)+"</td></tr></div>"
|
||||
pageText=pageText+PrintFooter()
|
||||
pageText = PrintHeader()+self.name+PrintMenu()
|
||||
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>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 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>Filename</b></td><td>"+str(gPronterPtr.filename)+"</td></tr></div>"
|
||||
pageText = pageText+PrintFooter()
|
||||
return pageText
|
||||
index.exposed = True
|
||||
|
||||
class LogPage(object):
|
||||
def __init__(self):
|
||||
self.name="<div id='title'>Pronterface Console</div>"
|
||||
self.name = "<div id='title'>Pronterface Console</div>"
|
||||
|
||||
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+=gPronterPtr.status.GetStatusText()
|
||||
pageText+="</div>"
|
||||
pageText=pageText+"<div id='console'>"+gWeblog+"</div>"
|
||||
pageText=pageText+"</body></html>"
|
||||
pageText = pageText+"<div id='console'>"+gWeblog+"</div>"
|
||||
pageText = pageText+"</body></html>"
|
||||
return pageText
|
||||
index.exposed = True
|
||||
|
||||
class ConsolePage(object):
|
||||
def __init__(self):
|
||||
self.name="<div id='title'>Pronterface Settings</div>"
|
||||
self.name = "<div id='title'>Pronterface Settings</div>"
|
||||
|
||||
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+=PrintFooter()
|
||||
return pageText
|
||||
|
@ -80,7 +80,7 @@ class ConnectButton(object):
|
|||
'tools.basic_auth.realm': 'My Print Server',
|
||||
'tools.basic_auth.users': users,
|
||||
'tools.basic_auth.encrypt': clear_text}
|
||||
|
||||
|
||||
class DisconnectButton(object):
|
||||
def index(self):
|
||||
#handle connect push, then reload page
|
||||
|
@ -129,7 +129,7 @@ class MoveButton(object):
|
|||
def axis(self, *args):
|
||||
if not args:
|
||||
raise cherrypy.HTTPError(400, "No Move Command Provided!")
|
||||
margs=list(args)
|
||||
margs = list(args)
|
||||
axis = margs.pop(0)
|
||||
if(margs and axis == "x"):
|
||||
distance = margs.pop(0)
|
||||
|
@ -149,12 +149,12 @@ class MoveButton(object):
|
|||
'tools.basic_auth.realm': 'My Print Server',
|
||||
'tools.basic_auth.users': users,
|
||||
'tools.basic_auth.encrypt': clear_text}
|
||||
|
||||
|
||||
class CustomButton(object):
|
||||
def button(self, *args):
|
||||
if not args:
|
||||
raise cherrypy.HTTPError(400, "No Custom Command Provided!")
|
||||
margs=list(args)
|
||||
margs = list(args)
|
||||
command = margs.pop(0)
|
||||
if(command):
|
||||
gPronterPtr.onecmd(command)
|
||||
|
@ -164,12 +164,12 @@ class CustomButton(object):
|
|||
'tools.basic_auth.realm': 'My Print Server',
|
||||
'tools.basic_auth.users': users,
|
||||
'tools.basic_auth.encrypt': clear_text}
|
||||
|
||||
|
||||
class HomeButton(object):
|
||||
def axis(self, *args):
|
||||
if not args:
|
||||
raise cherrypy.HTTPError(400, "No Axis Provided!")
|
||||
margs=list(args)
|
||||
margs = list(args)
|
||||
taxis = margs.pop(0)
|
||||
if(taxis == "x"):
|
||||
gPronterPtr.onecmd('home X')
|
||||
|
@ -183,41 +183,41 @@ class HomeButton(object):
|
|||
if(taxis == "all"):
|
||||
gPronterPtr.onecmd('home')
|
||||
return ReloadPage("Home All")
|
||||
|
||||
|
||||
axis.exposed = True
|
||||
axis._cp_config = {'tools.basic_auth.on': True,
|
||||
'tools.basic_auth.realm': 'My Print Server',
|
||||
'tools.basic_auth.users': users,
|
||||
'tools.basic_auth.encrypt': clear_text}
|
||||
|
||||
|
||||
class XMLstatus(object):
|
||||
def index(self):
|
||||
#handle connect push, then reload page
|
||||
txt='<?xml version="1.0"?>\n<pronterface>\n'
|
||||
state="Offline"
|
||||
txt='<?xml version = "1.0"?>\n<pronterface>\n'
|
||||
state = "Offline"
|
||||
if gPronterPtr.statuscheck or gPronterPtr.p.online:
|
||||
state="Idle"
|
||||
state = "Idle"
|
||||
if gPronterPtr.sdprinting:
|
||||
state="SDPrinting"
|
||||
state = "SDPrinting"
|
||||
if gPronterPtr.p.printing:
|
||||
state="Printing"
|
||||
state = "Printing"
|
||||
if gPronterPtr.paused:
|
||||
state="Paused"
|
||||
|
||||
txt=txt+'<state>'+state+'</state>\n'
|
||||
txt=txt+'<file>'+str(gPronterPtr.filename)+'</file>\n'
|
||||
txt=txt+'<status>'+str(gPronterPtr.status.GetStatusText())+'</status>\n'
|
||||
state = "Paused"
|
||||
|
||||
txt = txt+'<state>'+state+'</state>\n'
|
||||
txt = txt+'<file>'+str(gPronterPtr.filename)+'</file>\n'
|
||||
txt = txt+'<status>'+str(gPronterPtr.status.GetStatusText())+'</status>\n'
|
||||
try:
|
||||
temp = str(float(filter(lambda x:x.startswith("T:"),gPronterPtr.tempreport.split())[0].split(":")[1]))
|
||||
txt=txt+'<hotend>'+temp+'</hotend>\n'
|
||||
temp = str(float(filter(lambda x:x.startswith("T:"), gPronterPtr.tempreport.split())[0].split(":")[1]))
|
||||
txt = txt+'<hotend>'+temp+'</hotend>\n'
|
||||
except:
|
||||
txt=txt+'<hotend>NA</hotend>\n'
|
||||
txt = txt+'<hotend>NA</hotend>\n'
|
||||
pass
|
||||
try:
|
||||
temp = str(float(filter(lambda x:x.startswith("B:"),gPronterPtr.tempreport.split())[0].split(":")[1]))
|
||||
txt=txt+'<bed>'+temp+'</bed>\n'
|
||||
temp = str(float(filter(lambda x:x.startswith("B:"), gPronterPtr.tempreport.split())[0].split(":")[1]))
|
||||
txt = txt+'<bed>'+temp+'</bed>\n'
|
||||
except:
|
||||
txt=txt+'<bed>NA</bed>\n'
|
||||
txt = txt+'<bed>NA</bed>\n'
|
||||
pass
|
||||
if gPronterPtr.sdprinting:
|
||||
fractioncomplete = float(gPronterPtr.percentdone/100.0)
|
||||
|
@ -234,26 +234,26 @@ class XMLstatus(object):
|
|||
index.exposed = True
|
||||
|
||||
class WebInterface(object):
|
||||
|
||||
|
||||
def __init__(self, pface):
|
||||
if (sys.version_info[1] > 6):
|
||||
# 'allow_no_value' wasn't added until 2.7
|
||||
config = ConfigParser.SafeConfigParser(allow_no_value=True)
|
||||
# 'allow_no_value' wasn't added until 2.7
|
||||
config = ConfigParser.SafeConfigParser(allow_no_value = True)
|
||||
else:
|
||||
config = ConfigParser.SafeConfigParser()
|
||||
config = ConfigParser.SafeConfigParser()
|
||||
config.read(configfile(pface.web_auth_config or 'auth.config'))
|
||||
users[config.get("user", "user")] = config.get("user", "pass")
|
||||
self.pface = pface
|
||||
global gPronterPtr
|
||||
global gWeblog
|
||||
self.name="<div id='title'>Pronterface Web-Interface</div>"
|
||||
self.name = "<div id='title'>Pronterface Web-Interface</div>"
|
||||
gWeblog = ""
|
||||
gPronterPtr = self.pface
|
||||
gPronterPtr = self.pface
|
||||
|
||||
settings = SettingsPage()
|
||||
logpage = LogPage()
|
||||
console = ConsolePage()
|
||||
|
||||
|
||||
#actions
|
||||
connect = ConnectButton()
|
||||
disconnect = DisconnectButton()
|
||||
|
@ -264,9 +264,9 @@ class WebInterface(object):
|
|||
home = HomeButton()
|
||||
move = MoveButton()
|
||||
custom =CustomButton()
|
||||
|
||||
|
||||
def index(self):
|
||||
pageText=PrintHeader()+self.name+PrintMenu()
|
||||
pageText = PrintHeader()+self.name+PrintMenu()
|
||||
pageText+="<div id='content'>\n"
|
||||
pageText+="<div id='controls'>\n"
|
||||
pageText+="<ul><li><a href='/connect'>Connect</a></li>\n"
|
||||
|
@ -274,52 +274,52 @@ class WebInterface(object):
|
|||
pageText+="<li><a href='/reset'>Reset</a></li>\n"
|
||||
pageText+="<li><a href='/printbutton'>Print</a></li>\n"
|
||||
pageText+="<li><a href='/pausebutton'>Pause</a></li>\n"
|
||||
|
||||
|
||||
for i in gPronterPtr.cpbuttons:
|
||||
pageText+="<li><a href='/custom/button/"+i[1]+"'>"+i[0]+"</a></li>\n"
|
||||
|
||||
|
||||
#for i in gPronterPtr.custombuttons:
|
||||
# print(str(i));
|
||||
|
||||
|
||||
pageText+="</ul>\n"
|
||||
pageText+="</div>\n"
|
||||
pageText+="<div id='gui'>\n"
|
||||
pageText+="<div id='control_xy'>"
|
||||
pageText+="<img src='/images/control_xy.png' usemap='#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="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="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="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="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="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="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="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="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="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="137,105,165,140" href="/move/axis/x/.1" alt="X .1" title="X .1" />'
|
||||
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 = "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 = "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 = "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 = "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 = "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 = "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 = "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 = "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 = "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 = "137, 105, 165, 140" href = "/move/axis/x/.1" alt = "X .1" title = "X .1" />'
|
||||
|
||||
pageText+="</map>"
|
||||
pageText+="</div>\n" #endxy
|
||||
pageText+="<div id='control_z'>"
|
||||
pageText+="<img src='/images/control_z.png' usemap='#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,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,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,173,54,202" href="/move/axis/z/-10" alt="Z -10" title="Z -10" />'
|
||||
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, 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, 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, 173, 54, 202" href = "/move/axis/z/-10" alt = "Z -10" title = "Z -10" />'
|
||||
pageText+="</map>"
|
||||
#TODO Map Z Moves
|
||||
pageText+="</div>\n" #endz
|
||||
|
@ -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+="</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+=PrintFooter()
|
||||
return pageText
|
||||
|
||||
def AddLog(self, log):
|
||||
global gWeblog
|
||||
gWeblog=gWeblog+"</br>"+log
|
||||
gWeblog = gWeblog+"</br>"+log
|
||||
def AppendLog(self, log):
|
||||
global gWeblog
|
||||
gWeblog=re.sub("\n", "</br>", gWeblog)+log
|
||||
gWeblog = re.sub("\n", "</br>", gWeblog)+log
|
||||
index.exposed = True
|
||||
|
||||
class WebInterfaceStub(object):
|
||||
|
@ -357,7 +357,7 @@ class WebInterfaceStub(object):
|
|||
|
||||
def KillWebInterfaceThread():
|
||||
cherrypy.engine.exit()
|
||||
|
||||
|
||||
def StartWebInterfaceThread(webInterface):
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
cherrypy.config.update({'engine.autoreload_on':False})
|
||||
|
@ -372,7 +372,7 @@ def StartWebInterfaceThread(webInterface):
|
|||
'tools.staticfile.filename': imagefile('control_z.png'),
|
||||
}}
|
||||
cherrypy.config.update(configfile(webInterface.pface.web_config or "http.config"))
|
||||
cherrypy.quickstart(webInterface, '/', config=conf)
|
||||
cherrypy.quickstart(webInterface, '/', config = conf)
|
||||
|
||||
if __name__ == '__main__':
|
||||
cherrypy.config.update(configfile("http.config"))
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
# 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, os, math
|
||||
from bufferedcanvas import *
|
||||
from printrun_utils import *
|
||||
from printrun_utils import *
|
||||
|
||||
def sign(n):
|
||||
if n < 0: return -1
|
||||
|
@ -41,9 +41,9 @@ class XYButtons(BufferedCanvas):
|
|||
center = (124, 121)
|
||||
spacer = 7
|
||||
|
||||
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.keypad_bmp = wx.Image(imagefile("arrow_keys.png"),wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
||||
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.keypad_bmp = wx.Image(imagefile("arrow_keys.png"), wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
||||
self.keypad_idx = -1
|
||||
self.quadrant = None
|
||||
self.concentric = None
|
||||
|
@ -56,10 +56,10 @@ class XYButtons(BufferedCanvas):
|
|||
self.lastMove = None
|
||||
self.lastCorner = None
|
||||
|
||||
self.bgcolor = wx.Colour()
|
||||
self.bgcolor.SetFromName(bgcolor)
|
||||
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
|
||||
|
||||
self.bgcolor = wx.Colour()
|
||||
self.bgcolor.SetFromName(bgcolor)
|
||||
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
|
||||
|
||||
BufferedCanvas.__init__(self, parent, ID)
|
||||
self.SetSize(self.bg_bmp.GetSize())
|
||||
|
||||
|
@ -70,11 +70,11 @@ class XYButtons(BufferedCanvas):
|
|||
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
|
||||
self.Bind(wx.EVT_KEY_UP, self.OnKey)
|
||||
wx.GetTopLevelParent(self).Bind(wx.EVT_CHAR_HOOK, self.OnTopLevelKey)
|
||||
|
||||
|
||||
def disable(self):
|
||||
self.enabled = False
|
||||
self.update()
|
||||
|
||||
|
||||
def enable(self):
|
||||
self.enabled = True
|
||||
self.update()
|
||||
|
@ -84,7 +84,7 @@ class XYButtons(BufferedCanvas):
|
|||
self.moveCallback(*self.lastMove)
|
||||
if self.lastCorner:
|
||||
self.cornerCallback(self.lastCorner)
|
||||
|
||||
|
||||
def clearRepeat(self):
|
||||
self.lastMove = None
|
||||
self.lastCorner = None
|
||||
|
@ -95,7 +95,7 @@ class XYButtons(BufferedCanvas):
|
|||
pxlen = x1 - pos.x
|
||||
pylen = y1 - pos.y
|
||||
return abs(xlen*pylen-ylen*pxlen)/math.sqrt(xlen**2+ylen**2)
|
||||
|
||||
|
||||
def distanceToPoint(self, x1, y1, x2, y2):
|
||||
return math.sqrt((x1-x2)**2 + (y1-y2)**2)
|
||||
|
||||
|
@ -103,17 +103,17 @@ class XYButtons(BufferedCanvas):
|
|||
idx = self.keypad_idx + 1
|
||||
if idx > 2: idx = 0
|
||||
return idx
|
||||
|
||||
|
||||
def setKeypadIndex(self, idx):
|
||||
self.keypad_idx = idx
|
||||
self.update()
|
||||
|
||||
|
||||
def getMovement(self):
|
||||
xdir = [1, 0, -1, 0][self.quadrant]
|
||||
ydir = [0, 1, 0, -1][self.quadrant]
|
||||
magnitude = math.pow(10, self.concentric-1)
|
||||
return (magnitude * xdir, magnitude * ydir)
|
||||
|
||||
|
||||
def lookupConcentric(self, radius):
|
||||
idx = 0
|
||||
for r in XYButtons.concentric_circle_radii[1:]:
|
||||
|
@ -134,27 +134,27 @@ class XYButtons(BufferedCanvas):
|
|||
quadrant = 1 # Up
|
||||
else:
|
||||
quadrant = 2 # Left
|
||||
|
||||
|
||||
idx = self.lookupConcentric(radius)
|
||||
return (quadrant, idx)
|
||||
|
||||
|
||||
def mouseOverKeypad(self, mpos):
|
||||
for idx, kpos in XYButtons.keypad_positions.items():
|
||||
radius = self.distanceToPoint(mpos[0], mpos[1], kpos[0], kpos[1])
|
||||
if radius < 9:
|
||||
return idx
|
||||
return None
|
||||
|
||||
|
||||
def drawPartialPie(self, gc, center, r1, r2, angle1, angle2):
|
||||
p1 = wx.Point(center.x + r1*math.cos(angle1), center.y + r1*math.sin(angle1))
|
||||
|
||||
|
||||
path = gc.CreatePath()
|
||||
path.MoveToPoint(p1.x, p1.y)
|
||||
path.AddArc(center.x, center.y, r1, angle1, angle2, True)
|
||||
path.AddArc(center.x, center.y, r2, angle2, angle1, False)
|
||||
path.AddLineToPoint(p1.x, p1.y)
|
||||
gc.DrawPath(path)
|
||||
|
||||
|
||||
def highlightQuadrant(self, gc, quadrant, concentric):
|
||||
assert(quadrant >= 0 and quadrant <= 3)
|
||||
assert(concentric >= 0 and concentric <= 3)
|
||||
|
@ -175,13 +175,13 @@ class XYButtons(BufferedCanvas):
|
|||
elif quadrant == 3:
|
||||
a1, a2 = (math.pi*0.25, math.pi*0.75)
|
||||
center.y += inner_ring_radius
|
||||
|
||||
|
||||
r1 = XYButtons.concentric_circle_radii[concentric]
|
||||
r2 = XYButtons.concentric_circle_radii[concentric+1]
|
||||
|
||||
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
|
||||
|
||||
gc.PushState()
|
||||
|
@ -197,11 +197,11 @@ class XYButtons(BufferedCanvas):
|
|||
gc.DrawPath(path)
|
||||
gc.PopState()
|
||||
|
||||
def highlightCorner(self, gc, corner=0):
|
||||
def highlightCorner(self, gc, corner = 0):
|
||||
w, h = XYButtons.corner_size
|
||||
cx, cy = XYButtons.center
|
||||
ww, wh = self.GetSizeTuple()
|
||||
|
||||
|
||||
inset = 10
|
||||
if corner == 0:
|
||||
x, y = (cx - ww/2 + inset, cy - wh/2 + inset)
|
||||
|
@ -215,10 +215,10 @@ class XYButtons(BufferedCanvas):
|
|||
elif corner == 3:
|
||||
x, y = (cx - ww/2 + inset, cy + wh/2 - inset)
|
||||
self.drawCorner(gc, x+w/2, y-h/2, math.pi*3/2)
|
||||
|
||||
|
||||
|
||||
def draw(self, dc, w, h):
|
||||
dc.SetBackground(wx.Brush(self.bgcolor))
|
||||
dc.SetBackground(wx.Brush(self.bgcolor))
|
||||
dc.Clear()
|
||||
gc = wx.GraphicsContext.Create(dc)
|
||||
|
||||
|
@ -226,11 +226,11 @@ class XYButtons(BufferedCanvas):
|
|||
if self.bg_bmp:
|
||||
w, h = (self.bg_bmp.GetWidth(), self.bg_bmp.GetHeight())
|
||||
gc.DrawBitmap(self.bg_bmp, 0, 0, w, h)
|
||||
|
||||
|
||||
if self.enabled:
|
||||
# Brush and pen for grey overlay when mouse hovers over
|
||||
gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4))
|
||||
gc.SetBrush(wx.Brush(wx.Colour(0,0,0,128)))
|
||||
gc.SetPen(wx.Pen(wx.Colour(100, 100, 100, 172), 4))
|
||||
gc.SetBrush(wx.Brush(wx.Colour(0, 0, 0, 128)))
|
||||
|
||||
if self.concentric != None:
|
||||
if self.concentric < len(XYButtons.concentric_circle_radii):
|
||||
|
@ -238,16 +238,16 @@ class XYButtons(BufferedCanvas):
|
|||
self.highlightQuadrant(gc, self.quadrant, self.concentric)
|
||||
elif self.corner != None:
|
||||
self.highlightCorner(gc, self.corner)
|
||||
|
||||
|
||||
if self.keypad_idx >= 0:
|
||||
padw, padh = (self.keypad_bmp.GetWidth(), self.keypad_bmp.GetHeight())
|
||||
pos = XYButtons.keypad_positions[self.keypad_idx]
|
||||
pos = (pos[0] - padw/2 - 3, pos[1] - padh/2 - 3)
|
||||
gc.DrawBitmap(self.keypad_bmp, pos[0], pos[1], padw, padh)
|
||||
|
||||
|
||||
# Draw label overlays
|
||||
gc.SetPen(wx.Pen(wx.Colour(255,255,255,128), 1))
|
||||
gc.SetBrush(wx.Brush(wx.Colour(255,255,255,128+64)))
|
||||
gc.SetPen(wx.Pen(wx.Colour(255, 255, 255, 128), 1))
|
||||
gc.SetBrush(wx.Brush(wx.Colour(255, 255, 255, 128+64)))
|
||||
for idx, kpos in XYButtons.label_overlay_positions.items():
|
||||
if idx != self.concentric:
|
||||
r = kpos[2]
|
||||
|
@ -256,7 +256,7 @@ class XYButtons(BufferedCanvas):
|
|||
gc.SetPen(wx.Pen(self.bgcolor, 0))
|
||||
gc.SetBrush(wx.Brush(self.bgcolormask))
|
||||
gc.DrawRectangle(0, 0, w, h)
|
||||
|
||||
|
||||
|
||||
# Used to check exact position of keypad dots, should we ever resize the bg image
|
||||
# for idx, kpos in XYButtons.label_overlay_positions.items():
|
||||
|
@ -289,7 +289,7 @@ class XYButtons(BufferedCanvas):
|
|||
else:
|
||||
evt.Skip()
|
||||
return
|
||||
|
||||
|
||||
if self.moveCallback:
|
||||
self.concentric = self.keypad_idx
|
||||
x, y = self.getMovement()
|
||||
|
@ -301,7 +301,7 @@ class XYButtons(BufferedCanvas):
|
|||
def OnMotion(self, event):
|
||||
if not self.enabled:
|
||||
return
|
||||
|
||||
|
||||
oldcorner = self.corner
|
||||
oldq, oldc = self.quadrant, self.concentric
|
||||
|
||||
|
@ -318,7 +318,7 @@ class XYButtons(BufferedCanvas):
|
|||
# If mouse hovers in space between quadrants, don't commit to a quadrant
|
||||
if riseDist <= XYButtons.spacer or fallDist <= XYButtons.spacer:
|
||||
self.quadrant = None
|
||||
|
||||
|
||||
cx, cy = XYButtons.center
|
||||
if mpos.x < cx and mpos.y < cy:
|
||||
self.corner = 0
|
||||
|
@ -335,7 +335,7 @@ class XYButtons(BufferedCanvas):
|
|||
def OnLeftDown(self, event):
|
||||
if not self.enabled:
|
||||
return
|
||||
|
||||
|
||||
# Take focus when clicked so that arrow keys can control movement
|
||||
self.SetFocus()
|
||||
|
||||
|
@ -362,7 +362,7 @@ class XYButtons(BufferedCanvas):
|
|||
self.setKeypadIndex(-1)
|
||||
else:
|
||||
self.setKeypadIndex(idx)
|
||||
|
||||
|
||||
def OnLeaveWindow(self, evt):
|
||||
self.quadrant = None
|
||||
self.concentric = None
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
# 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, os, math
|
||||
from bufferedcanvas import *
|
||||
from printrun_utils import *
|
||||
from printrun_utils import *
|
||||
|
||||
def sign(n):
|
||||
if n < 0: return -1
|
||||
|
@ -32,8 +32,8 @@ class ZButtons(BufferedCanvas):
|
|||
3: None
|
||||
}
|
||||
|
||||
def __init__(self, parent, moveCallback=None, bgcolor="#FFFFFF", ID=-1):
|
||||
self.bg_bmp = wx.Image(imagefile("control_z.png"),wx.BITMAP_TYPE_PNG).ConvertToBitmap()
|
||||
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.range = None
|
||||
self.direction = None
|
||||
self.orderOfMagnitudeIdx = 0 # 0 means '1', 1 means '10', 2 means '100', etc.
|
||||
|
@ -42,9 +42,9 @@ class ZButtons(BufferedCanvas):
|
|||
# Remember the last clicked value, so we can repeat when spacebar pressed
|
||||
self.lastValue = None
|
||||
|
||||
self.bgcolor = wx.Colour()
|
||||
self.bgcolor.SetFromName(bgcolor)
|
||||
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
|
||||
self.bgcolor = wx.Colour()
|
||||
self.bgcolor.SetFromName(bgcolor)
|
||||
self.bgcolormask = wx.Colour(self.bgcolor.Red(), self.bgcolor.Green(), self.bgcolor.Blue(), 128)
|
||||
|
||||
BufferedCanvas.__init__(self, parent, ID)
|
||||
|
||||
|
@ -59,7 +59,7 @@ class ZButtons(BufferedCanvas):
|
|||
def disable(self):
|
||||
self.enabled = False
|
||||
self.update()
|
||||
|
||||
|
||||
def enable(self):
|
||||
self.enabled = True
|
||||
self.update()
|
||||
|
@ -78,7 +78,7 @@ class ZButtons(BufferedCanvas):
|
|||
return idx
|
||||
idx += 1
|
||||
return None
|
||||
|
||||
|
||||
def highlight(self, gc, rng, dir):
|
||||
assert(rng >= -1 and rng <= 3)
|
||||
assert(dir >= -1 and dir <= 1)
|
||||
|
@ -93,13 +93,13 @@ class ZButtons(BufferedCanvas):
|
|||
gc.DrawRoundedRectangle(x, y, w, h, 4)
|
||||
# gc.DrawRectangle(x, y, w, h)
|
||||
# self.drawPartialPie(dc, center, r1-inner_ring_radius, r2-inner_ring_radius, a1+fudge, a2-fudge)
|
||||
|
||||
|
||||
def getRangeDir(self, pos):
|
||||
ydelta = ZButtons.center[1] - pos[1]
|
||||
return (self.lookupRange(abs(ydelta)), sign(ydelta))
|
||||
|
||||
def draw(self, dc, w, h):
|
||||
dc.SetBackground(wx.Brush(self.bgcolor))
|
||||
dc.SetBackground(wx.Brush(self.bgcolor))
|
||||
dc.Clear()
|
||||
gc = wx.GraphicsContext.Create(dc)
|
||||
if self.bg_bmp:
|
||||
|
@ -108,16 +108,16 @@ class ZButtons(BufferedCanvas):
|
|||
|
||||
if self.enabled:
|
||||
# Draw label overlays
|
||||
gc.SetPen(wx.Pen(wx.Colour(255,255,255,128), 1))
|
||||
gc.SetBrush(wx.Brush(wx.Colour(255,255,255,128+64)))
|
||||
gc.SetPen(wx.Pen(wx.Colour(255, 255, 255, 128), 1))
|
||||
gc.SetBrush(wx.Brush(wx.Colour(255, 255, 255, 128+64)))
|
||||
for idx, kpos in ZButtons.label_overlay_positions.items():
|
||||
if kpos and idx != self.range:
|
||||
r = kpos[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
|
||||
gc.SetPen(wx.Pen(wx.Colour(100,100,100,172), 4))
|
||||
gc.SetBrush(wx.Brush(wx.Colour(0,0,0,128)))
|
||||
gc.SetPen(wx.Pen(wx.Colour(100, 100, 100, 172), 4))
|
||||
gc.SetBrush(wx.Brush(wx.Colour(0, 0, 0, 128)))
|
||||
if self.range != None and self.direction != None:
|
||||
self.highlight(gc, self.range, self.direction)
|
||||
else:
|
||||
|
@ -132,7 +132,7 @@ class ZButtons(BufferedCanvas):
|
|||
def OnMotion(self, event):
|
||||
if not self.enabled:
|
||||
return
|
||||
|
||||
|
||||
oldr, oldd = self.range, self.direction
|
||||
|
||||
mpos = event.GetPosition()
|
||||
|
|
|
@ -1,76 +1,76 @@
|
|||
# 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,math
|
||||
import wx, math
|
||||
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):
|
||||
o=stl(None)
|
||||
datal=len(data)
|
||||
datah=len(data[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)
|
||||
datal = len(data)
|
||||
datah = len(data[0])
|
||||
#create bottom:
|
||||
bmidpoint=(pscale*(datal-1)/2.0,pscale*(datah-1)/2.0)
|
||||
#print range(datal),bmidpoint
|
||||
for i in zip(range(datal+1)[:-1],range(datal+1)[1:])[:-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],[[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([[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([[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]])]
|
||||
bmidpoint = (pscale*(datal-1)/2.0, pscale*(datah-1)/2.0)
|
||||
#print range(datal), bmidpoint
|
||||
for i in zip(range(datal+1)[:-1], range(datal+1)[1:])[:-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],[[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([[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([[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]
|
||||
pass
|
||||
#print o.facets[-4:]
|
||||
for i in zip(range(datah+1)[:-1],range(datah+1)[1:])[:-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[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]])]
|
||||
for i in zip(range(datah+1)[:-1], range(datah+1)[1:])[:-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[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]])]
|
||||
#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[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], 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[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
|
||||
for i in xrange(datah-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+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, 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]])]
|
||||
#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
|
||||
def zimage(name,out):
|
||||
i=wx.Image(name)
|
||||
s=i.GetSize()
|
||||
print len(map(ord,i.GetData()[::3]))
|
||||
b=map(ord,i.GetData()[::3])
|
||||
data=[]
|
||||
def zimage(name, out):
|
||||
i = wx.Image(name)
|
||||
s = i.GetSize()
|
||||
print len(map(ord, i.GetData()[::3]))
|
||||
b = map(ord, i.GetData()[::3])
|
||||
data = []
|
||||
for i in xrange(s[0]):
|
||||
data+=[b[i*s[1]:(i+1)*s[1]]]
|
||||
#data=[i[::5] for i in data[::5]]
|
||||
emitstl(out,genscape(data,zscale=0.1).facets,name)
|
||||
#data = [i[::5] for i in data[::5]]
|
||||
emitstl(out, genscape(data, zscale = 0.1).facets, name)
|
||||
|
||||
"""
|
||||
class scapewin(wx.Frame):
|
||||
def __init__(self,size=(400,530)):
|
||||
wx.Frame.__init__(self,None,title="Right-click to load an image",size=size)
|
||||
self.SetIcon(wx.Icon("plater.ico",wx.BITMAP_TYPE_ICO))
|
||||
def __init__(self, size = (400, 530)):
|
||||
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.SetClientSize(size)
|
||||
self.panel=wx.Panel(self,size=size)
|
||||
|
||||
self.panel = wx.Panel(self, size = size)
|
||||
|
||||
|
||||
"""
|
||||
if __name__ == '__main__':
|
||||
|
@ -80,6 +80,5 @@ if __name__ == '__main__':
|
|||
main.Show()
|
||||
app.MainLoop()
|
||||
"""
|
||||
zimage("catposthtmap2.jpg","testobj.stl")
|
||||
zimage("catposthtmap2.jpg", "testobj.stl")
|
||||
del a
|
||||
|
||||
|
|
789
pronsole.py
789
pronsole.py
File diff suppressed because it is too large
Load Diff
1726
pronterface.py
1726
pronterface.py
File diff suppressed because it is too large
Load Diff
12
setup.py
12
setup.py
|
@ -1,17 +1,17 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# 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/>.
|
||||
|
||||
|
@ -43,7 +43,7 @@ class install (_install):
|
|||
except:
|
||||
self.warn ("Could not write installed files list %s" % \
|
||||
INSTALLED_FILES)
|
||||
return
|
||||
return
|
||||
file.write (data)
|
||||
file.close ()
|
||||
|
||||
|
@ -66,7 +66,7 @@ class uninstall (_install):
|
|||
except:
|
||||
self.warn ("Could not read installed files list %s" % \
|
||||
INSTALLED_FILES)
|
||||
return
|
||||
return
|
||||
files = file.readlines ()
|
||||
file.close ()
|
||||
prepend = ""
|
||||
|
@ -145,7 +145,7 @@ setup (
|
|||
license = "GPLv3",
|
||||
data_files = data_files,
|
||||
packages = ["printrun", "printrun.svg"],
|
||||
scripts = ["pronsole.py", "pronterface.py", "plater.py"],
|
||||
scripts = ["pronsole.py", "pronterface.py", "plater.py", "printcore.py"],
|
||||
cmdclass = {"uninstall" : uninstall,
|
||||
"install" : install,
|
||||
"install_data" : install_data}
|
||||
|
|
Loading…
Reference in New Issue