Merge pull request #279 from iXce/connection-rework

Connection rework, coding style rework
master
kliment 2012-09-05 01:19:07 -07:00
commit 093f6a4529
41 changed files with 3446 additions and 3325 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
*.pyc
.pronsolerc
*.swp
*.bak

26
README.cleanup Normal file
View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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"

View File

@ -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 ""

View File

@ -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 ""

View File

@ -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:

396
printcore.py Executable file
View File

@ -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()

View File

@ -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))):

View File

@ -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()

View File

@ -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:

View File

@ -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()

View File

@ -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()

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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):

View File

@ -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()

View File

@ -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)

View File

@ -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")

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -3,4 +3,4 @@
from pyparsing import Literal, Combine
from .identifier import identifier
atkeyword = Combine(Literal("@") + identifier)
atkeyword = Combine(Literal("@") + identifier)

View File

@ -5,4 +5,3 @@
from pyparsing import nestedExpr
block = nestedExpr(opener="{", closer="}")

View File

@ -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()
)
)

View File

@ -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))

View File

@ -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

View File

@ -48,4 +48,4 @@ transformList = delimitedList(Group(transform), delim=maybeComma)
if __name__ == '__main__':
from tests.test_css import *
unittest.main()
unittest.main()

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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"))

View File

@ -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

View File

@ -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()

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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}