Tests compiling Replath
parent
d389a67ab2
commit
bfd0b378a5
|
@ -1,3 +1,8 @@
|
|||
Dependencies
|
||||
--
|
||||
sudo apt-get install potrace
|
||||
(among others)
|
||||
|
||||
Author
|
||||
--
|
||||
pyRepRap and Replath by Stefan Blanke (<http://reprap.org/wiki/Builders/pyRepRap> and <http://reprap.org/wiki/Builders/Replath>)
|
||||
|
|
|
@ -215,7 +215,6 @@ def _getNotification(serialPort):
|
|||
|
||||
|
||||
class extruderClass:
|
||||
tempScaler = 0
|
||||
"""Used to control a RepRap thermoplast extruder.
|
||||
An instance is automatically created in the reprap module, so for
|
||||
basic use just use reprap.extruder rather than defining a new one
|
||||
|
@ -229,10 +228,8 @@ class extruderClass:
|
|||
self.hb = 20 # Variable Preference
|
||||
self.hm = 1.66667 # Variable Preference
|
||||
self.absZero = 273.15 # Static, K
|
||||
#self.rz = 29000 # Variable Preference
|
||||
self.rz = 353700 # Variable Preference
|
||||
#self.beta = 3480 # Variable Preference
|
||||
self.beta = 4267 # Variable Preference
|
||||
self.rz = 29000 # Variable Preference
|
||||
self.beta = 3480 # Variable Preference
|
||||
self.vdd = 5.0 # Static, volts
|
||||
self.cap = 0.0000001 # Variable Preference
|
||||
|
||||
|
@ -261,7 +258,7 @@ class extruderClass:
|
|||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [int(direction), int(speed)] ) ##no command being sent, whats going on?
|
||||
p.send()
|
||||
else:
|
||||
raise _RepRapError("Invalid direction or speed value")
|
||||
raise RepRapError("Invalid direction or speed value")
|
||||
|
||||
def _calculateResistance(self, picTemp, calibrationPicTemp):
|
||||
"""Calculate resistance from pic timer value"""
|
||||
|
@ -330,7 +327,6 @@ class extruderClass:
|
|||
self._autoTempRange()
|
||||
rawHeat, calibration = self._getRawTemp()
|
||||
while rawHeat == 255 or rawHeat == 0:
|
||||
# TODO very bad as will hang in what should be a tight loop
|
||||
time.sleep(0.1)
|
||||
self._autoTempRange()
|
||||
res = self._calculateResistance( rawHeat, calibration )
|
||||
|
@ -338,7 +334,7 @@ class extruderClass:
|
|||
#print rawHeat, res, temp
|
||||
return round(temp, 1) #there is no point returning more points than this
|
||||
|
||||
def setTemp(self, temperature, null):
|
||||
def setTemp(self, temperature):
|
||||
"""Set the extruder target temperature (degrees Celsius)"""
|
||||
self.requestedTemperature = temperature
|
||||
#if(math.abs(self.requestedTemperature - extrusionTemp) > 5):
|
||||
|
@ -480,7 +476,7 @@ class axisClass:
|
|||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_FORWARD, int(speed)] )
|
||||
p.send()
|
||||
else:
|
||||
raise _RepRapError("Invalid speed value")
|
||||
raise RepRapError("Invalid speed value")
|
||||
|
||||
def backward(self, speed = None):
|
||||
"""Spin axis backward at given speed (0-255)
|
||||
|
@ -494,7 +490,7 @@ class axisClass:
|
|||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_REVERSE, int(speed)] )
|
||||
p.send()
|
||||
else:
|
||||
raise _RepRapError("Invalid speed value")
|
||||
raise RepRapError("Invalid speed value")
|
||||
|
||||
def getSensors(self):
|
||||
"""Debug only. Returns raw PIC port bytes)"""
|
||||
|
@ -522,7 +518,7 @@ class axisClass:
|
|||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOS, posMSB, posLSB] )
|
||||
p.send()
|
||||
else:
|
||||
raise _RepRapError("Invalid position value")
|
||||
raise RepRapError("Invalid position value")
|
||||
|
||||
def free(self):
|
||||
"""Power off coils on stepper"""
|
||||
|
@ -566,7 +562,7 @@ class axisClass:
|
|||
if not notif.dataBytes[0] == CMD_SEEK:
|
||||
raise _RepRapError("Expected seek notification")
|
||||
else:
|
||||
raise _RepRapError("Invalid speed or position value")
|
||||
raise RepRapError("Invalid speed or position value")
|
||||
|
||||
def homeReset(self, speed = None, waitArrival = True):
|
||||
"""Go to 0 position. If waitArrival is True, funtion waits until reset is compete to return"""
|
||||
|
@ -582,7 +578,7 @@ class axisClass:
|
|||
if not notif.dataBytes[0] == CMD_HOMERESET:
|
||||
raise _RepRapError("Expected home reset notification")
|
||||
else:
|
||||
raise _RepRapError("Invalid speed value")
|
||||
raise RepRapError("Invalid speed value")
|
||||
|
||||
def setNotify(self):
|
||||
"""Set axis to notify on arrivals"""
|
||||
|
@ -595,7 +591,7 @@ class axisClass:
|
|||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SYNC, int(syncMode)] )
|
||||
p.send()
|
||||
else:
|
||||
raise _RepRapError("Invalid sync mode")
|
||||
raise RepRapError("Invalid sync mode")
|
||||
|
||||
def _DDA( self, seekTo, slaveDelta, speed = False, waitArrival = True):
|
||||
"""Set DDA mode"""
|
||||
|
@ -615,18 +611,17 @@ class axisClass:
|
|||
"""Set stepper motor power (0-100%)"""
|
||||
power = int( float(power) * 0.63 )
|
||||
if power >=0 and power <=0x3F:
|
||||
#p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, int( power * 0.63 )] ) # This is a value from 0 to 63 (6 bits)
|
||||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, power] ) # This is a value from 0 to 63 (6 bits)
|
||||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, int( power * 0.63 )] ) # This is a value from 0 to 63 (6 bits)
|
||||
p.send()
|
||||
else:
|
||||
raise _RepRapError("Invalid power value")
|
||||
raise RepRapError("Invalid power value")
|
||||
|
||||
def setSpeed(self, speed):
|
||||
"""Set axis move speed (0-255)"""
|
||||
if speed >= 0 and speed <= 0xFF:
|
||||
self.speed = speed
|
||||
else:
|
||||
raise _RepRapError("Invalid speed value")
|
||||
raise RepRapError("Invalid speed value")
|
||||
|
||||
def setStepsPerMM(self, spmm):
|
||||
"""Set axis steps per millimeter"""
|
||||
|
@ -672,17 +667,12 @@ class cartesianClass:
|
|||
if not waitArrival:
|
||||
print "WARNING : Reseting all axies at the same time is unstable. suggest using waitArrival = True option."
|
||||
#z is done first so we don't break anything we just made
|
||||
if self.z.active:
|
||||
if self.z.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "Z Reset"
|
||||
|
||||
if self.x.active:
|
||||
if self.x.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "X Reset"
|
||||
|
||||
if self.y.active:
|
||||
if self.y.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "Y Reset"
|
||||
if self.z.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "Z Reset"
|
||||
if self.x.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "X Reset"
|
||||
if self.y.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "Y Reset"
|
||||
|
||||
# TODO add a way to collect all three notifications (in whatever order) then check they are all there. this will allow symultanious axis movement and use of waitArrival
|
||||
# This requires snap receiver to search packets rather than just returning oldest one. probably need to do this anyway
|
||||
|
@ -766,36 +756,21 @@ class cartesianClass:
|
|||
|
||||
def stop(self):
|
||||
"""Stop all motors (but retain current)"""
|
||||
if self.x.active:
|
||||
self.x.forward(0)
|
||||
|
||||
if self.y.active:
|
||||
self.y.forward(0)
|
||||
|
||||
if self.z.active:
|
||||
self.z.forward(0)
|
||||
self.x.forward(0)
|
||||
self.y.forward(0)
|
||||
self.z.forward(0)
|
||||
|
||||
def free(self):
|
||||
"""Free all motors (no current on coils)"""
|
||||
if self.x.active:
|
||||
self.x.free()
|
||||
|
||||
if self.y.active:
|
||||
self.y.free()
|
||||
|
||||
if self.z.active:
|
||||
self.z.free()
|
||||
self.x.free()
|
||||
self.y.free()
|
||||
self.z.free()
|
||||
|
||||
def setPower(self, power):
|
||||
"""Set stepper power (0-100)"""
|
||||
if self.x.active:
|
||||
self.x.setPower(power)
|
||||
|
||||
if self.y.active:
|
||||
self.y.setPower(power)
|
||||
|
||||
if self.z.active:
|
||||
self.z.setPower(power)
|
||||
self.x.setPower(power)
|
||||
self.y.setPower(power)
|
||||
self.z.setPower(power)
|
||||
|
||||
#def lockout():
|
||||
#keep sending power down commands to all board every second
|
||||
|
@ -803,14 +778,9 @@ class cartesianClass:
|
|||
def setSpeed(self, speed):
|
||||
"""Set axies move speed (0-255)"""
|
||||
self.speed = speed
|
||||
if self.x.active:
|
||||
self.x.setSpeed(speed)
|
||||
|
||||
if self.y.active:
|
||||
self.y.setSpeed(speed)
|
||||
|
||||
if self.z.active:
|
||||
self.z.setSpeed(speed)
|
||||
self.x.setSpeed(speed)
|
||||
self.y.setSpeed(speed)
|
||||
self.z.setSpeed(speed)
|
||||
|
||||
def setStepsPerMM(self, spmm):
|
||||
"""Set axies steps per millimeter"""
|
|
@ -167,10 +167,10 @@ def circleStroke(x1, y1, x2, y2, radius, resolution, fillDensity = False ):
|
|||
# reversing these point lets locus be drawn in one continual motion
|
||||
poly.addPoint( toolpath.Point(x2 - rsintheta, y2 + rcostheta) )
|
||||
poly.addPoint( toolpath.Point(x1 - rsintheta, y1 + rcostheta) )
|
||||
poly.addPolygon( arc(x1, y1, r, theta + startOffset, theta + endOffset, resolution) )
|
||||
poly.addPolygon( arc(x1, y1, r, theta + startOffset, theta + endOffset, resolution, fillDensity = False) )
|
||||
poly.addPoint( toolpath.Point(x1 + rsintheta, y1 - rcostheta) )
|
||||
poly.addPoint( toolpath.Point(x2 + rsintheta, y2 - rcostheta) )
|
||||
poly.addPolygon( arc(x2, y2, r, theta - startOffset, theta - endOffset, resolution) )
|
||||
poly.addPolygon( arc(x2, y2, r, theta - startOffset, theta - endOffset, resolution, fillDensity = False) )
|
||||
return poly
|
||||
|
||||
def fill(polygon, fillDensity):
|
|
@ -23,7 +23,6 @@ along with pyRepRap. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
import serial, exceptions, threading, time
|
||||
from __init__ import _RepRapError
|
||||
|
||||
|
||||
SYNC_BYTE = 0x54
|
||||
|
@ -45,7 +44,7 @@ def openSerial( port = 0, rate = 19200, tout = 60 ):
|
|||
try:
|
||||
serialPort = serial.Serial( port, rate, timeout = tout )
|
||||
except:
|
||||
raise _RepRapError("You do not have permissions to use the serial port, try running as root")
|
||||
raise RepRapError("You do not have permissions to use the serial port, try running as root")
|
||||
|
||||
|
||||
def closeSerial():
|
|
@ -0,0 +1,169 @@
|
|||
#!/usr/bin/python
|
||||
import serial, reprap, time, sys
|
||||
|
||||
reprap.openSerial( 0, 19200, 60 )
|
||||
|
||||
# these devices are present in network
|
||||
reprap.cartesian.x.active = True
|
||||
reprap.cartesian.y.active = True
|
||||
reprap.cartesian.z.active = True
|
||||
reprap.extruder.active = True
|
||||
reprap.cartesian.x.setNotify()
|
||||
reprap.cartesian.y.setNotify()
|
||||
reprap.cartesian.z.setNotify()
|
||||
reprap.cartesian.x.limit = 2700
|
||||
reprap.cartesian.y.limit = 2500
|
||||
reprap.cartesian.y.limit = 2000
|
||||
|
||||
def printHelp():
|
||||
print "\nreprapcontrol command [args]"
|
||||
print " Commands:"
|
||||
print " stop Stop all axies"
|
||||
print " reset Send all axies to home"
|
||||
print " pos Print current position"
|
||||
print " goto [x] [y] [z] Go to specified position"
|
||||
print " power [0 to 63] Set power level"
|
||||
print " speed [0 to 255] Set steper speed"
|
||||
print " go Test routine"
|
||||
print " free Power off steper motors"
|
||||
print " run [x/y] [speed] Spin motor forwards"
|
||||
print " runb [x/y] [speed] Spin motor backwards"
|
||||
print " step [x/y/z] Step motor forward"
|
||||
print " stepb [x/y/z] Step motor backwards"
|
||||
|
||||
def printPos():
|
||||
x, y, z = reprap.cartesian.getPos()
|
||||
print "Location [" + str(x) + ", " + str(y) + ", " + str(z) + "]"
|
||||
|
||||
print "================================================================"
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
printHelp()
|
||||
|
||||
|
||||
|
||||
########### Cartesian control commands #########
|
||||
|
||||
# Stop all steppers
|
||||
if sys.argv[1] == "stop":
|
||||
reprap.cartesian.stop()
|
||||
|
||||
# Reset all axies
|
||||
elif sys.argv[1] == "reset":
|
||||
reprap.cartesian.homeReset( waitArrival = True, speed = 220 )
|
||||
|
||||
# Print current positon
|
||||
elif sys.argv[1] == "pos":
|
||||
printPos()
|
||||
|
||||
# Goto a specific location
|
||||
elif sys.argv[1] == "goto":
|
||||
reprap.cartesian.seek( ( int(sys.argv[2]), int(sys.argv[3]), int(sys.argv[4]) ), speed = 200, waitArrival = True)
|
||||
|
||||
# Set stepper power (%)
|
||||
elif sys.argv[1] == "power":
|
||||
reprap.cartesian.setPower( int( sys.argv[2] ) ) # This is a value from 0 to 63 (6 bits)
|
||||
|
||||
# Free motors (switch off all coils)
|
||||
elif sys.argv[1] == "free":
|
||||
reprap.cartesian.free()
|
||||
|
||||
# Test routine
|
||||
elif sys.argv[1] == "go":
|
||||
reprap.cartesian.seek( (1000, 1000, 0), 200, True )
|
||||
time.sleep(2)
|
||||
reprap.cartesian.seek( (500, 1000, 0), 200, True )
|
||||
time.sleep(2)
|
||||
reprap.cartesian.seek( (500, 500, 0), 200, True )
|
||||
time.sleep(2)
|
||||
reprap.cartesian.seek( (10, 10, 0), 200, True )
|
||||
|
||||
|
||||
|
||||
############## control of individual steppers #############
|
||||
|
||||
# Spin stepper forwards
|
||||
elif sys.argv[1] == "run": # run axis
|
||||
if sys.argv[2] == "x":
|
||||
reprap.cartesian.x.forward( int(sys.argv[3]) )
|
||||
elif sys.argv[2] == "y":
|
||||
reprap.cartesian.y.forward( int(sys.argv[3]) )
|
||||
elif sys.argv[2] == "z":
|
||||
reprap.cartesian.z.forward( int(sys.argv[3]) )
|
||||
|
||||
# Spin stepper backwards
|
||||
elif sys.argv[1] == "runb": #runb axis
|
||||
if sys.argv[2] == "x":
|
||||
reprap.cartesian.x.backward( int(sys.argv[3]) )
|
||||
elif sys.argv[2] == "y":
|
||||
reprap.cartesian.y.backward( int(sys.argv[3]) )
|
||||
elif sys.argv[2] == "z":
|
||||
reprap.cartesian.z.backward( int(sys.argv[3]) )
|
||||
|
||||
# Step motor forwards
|
||||
elif sys.argv[1] == "step":
|
||||
if sys.argv[2] == "x":
|
||||
reprap.cartesian.x.forward1()
|
||||
elif sys.argv[2] == "y":
|
||||
reprap.cartesian.y.forward1()
|
||||
elif sys.argv[2] == "z":
|
||||
reprap.cartesian.z.forward1()
|
||||
|
||||
# Step motor backwards
|
||||
elif sys.argv[1] == "stepb":
|
||||
if sys.argv[2] == "x":
|
||||
reprap.cartesian.x.backward1()
|
||||
elif sys.argv[2] == "y":
|
||||
reprap.cartesian.y.backward1()
|
||||
elif sys.argv[2] == "z":
|
||||
reprap.cartesian.z.backward1()
|
||||
|
||||
|
||||
|
||||
################# control of extruder #####################
|
||||
|
||||
# Test extrder motor
|
||||
elif sys.argv[1] == "motor":
|
||||
nn = 0
|
||||
while 1:
|
||||
if nn > 0:
|
||||
nn = 0
|
||||
else:
|
||||
nn = 150
|
||||
reprap.extruder.setMotor(reprap.CMD_REVERSE, nn)
|
||||
time.sleep(1)
|
||||
|
||||
elif sys.argv[1] == "getinfo":
|
||||
mtype = reprap.extruder.getModuleType()
|
||||
version = reprap.extruder.getVersion()
|
||||
print "module", mtype, "version", version
|
||||
|
||||
elif sys.argv[1] == "heat":
|
||||
reprap.extruder.setHeat(255, 255, 255, 255)
|
||||
|
||||
#setHeat(self, lowHeat, highHeat, tempTarget, tempMax
|
||||
|
||||
elif sys.argv[1] == "temp":
|
||||
print "Temp is ", reprap.extruder.getTemp()
|
||||
|
||||
|
||||
|
||||
############### scan network for devices ###################
|
||||
|
||||
# Scan snap network
|
||||
elif sys.argv[1] == "scan":
|
||||
reprap.scanNetwork()
|
||||
|
||||
# Test comms
|
||||
elif sys.argv[1] == "test":
|
||||
reprap.testComms()
|
||||
|
||||
|
||||
else:
|
||||
printHelp()
|
||||
|
||||
reprap.closeSerial()
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/python
|
||||
import wx, reprap, reprap.controlpanels
|
||||
|
||||
if __name__ == "__main__":
|
||||
# TODO put try here with message if failes
|
||||
reprap.openSerial( 0, 19200, 60 )
|
||||
reprap.cartesian.x.active = True
|
||||
reprap.cartesian.y.active = True
|
||||
reprap.cartesian.z.active = True
|
||||
reprap.extruder.active = True
|
||||
reprap.cartesian.x.setNotify()
|
||||
reprap.cartesian.y.setNotify()
|
||||
reprap.cartesian.z.setNotify()
|
||||
reprap.cartesian.setPower(70)
|
||||
reprap.cartesian.setSpeed(220)
|
||||
|
||||
app = wx.PySimpleApp(0)
|
||||
wx.InitAllImageHandlers()
|
||||
frame_main = reprap.controlpanels.MainControlFrame(None, -1, "")
|
||||
app.SetTopWindow(frame_main)
|
||||
frame_main.Show()
|
||||
app.MainLoop()
|
||||
|
||||
reprap.closeSerial()
|
|
@ -215,6 +215,7 @@ def _getNotification(serialPort):
|
|||
|
||||
|
||||
class extruderClass:
|
||||
tempScaler = 0
|
||||
"""Used to control a RepRap thermoplast extruder.
|
||||
An instance is automatically created in the reprap module, so for
|
||||
basic use just use reprap.extruder rather than defining a new one
|
||||
|
@ -228,8 +229,10 @@ class extruderClass:
|
|||
self.hb = 20 # Variable Preference
|
||||
self.hm = 1.66667 # Variable Preference
|
||||
self.absZero = 273.15 # Static, K
|
||||
self.rz = 29000 # Variable Preference
|
||||
self.beta = 3480 # Variable Preference
|
||||
#self.rz = 29000 # Variable Preference
|
||||
self.rz = 353700 # Variable Preference
|
||||
#self.beta = 3480 # Variable Preference
|
||||
self.beta = 4267 # Variable Preference
|
||||
self.vdd = 5.0 # Static, volts
|
||||
self.cap = 0.0000001 # Variable Preference
|
||||
|
||||
|
@ -258,7 +261,7 @@ class extruderClass:
|
|||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [int(direction), int(speed)] ) ##no command being sent, whats going on?
|
||||
p.send()
|
||||
else:
|
||||
raise RepRapError("Invalid direction or speed value")
|
||||
raise _RepRapError("Invalid direction or speed value")
|
||||
|
||||
def _calculateResistance(self, picTemp, calibrationPicTemp):
|
||||
"""Calculate resistance from pic timer value"""
|
||||
|
@ -327,6 +330,7 @@ class extruderClass:
|
|||
self._autoTempRange()
|
||||
rawHeat, calibration = self._getRawTemp()
|
||||
while rawHeat == 255 or rawHeat == 0:
|
||||
# TODO very bad as will hang in what should be a tight loop
|
||||
time.sleep(0.1)
|
||||
self._autoTempRange()
|
||||
res = self._calculateResistance( rawHeat, calibration )
|
||||
|
@ -334,7 +338,7 @@ class extruderClass:
|
|||
#print rawHeat, res, temp
|
||||
return round(temp, 1) #there is no point returning more points than this
|
||||
|
||||
def setTemp(self, temperature):
|
||||
def setTemp(self, temperature, null):
|
||||
"""Set the extruder target temperature (degrees Celsius)"""
|
||||
self.requestedTemperature = temperature
|
||||
#if(math.abs(self.requestedTemperature - extrusionTemp) > 5):
|
||||
|
@ -476,7 +480,7 @@ class axisClass:
|
|||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_FORWARD, int(speed)] )
|
||||
p.send()
|
||||
else:
|
||||
raise RepRapError("Invalid speed value")
|
||||
raise _RepRapError("Invalid speed value")
|
||||
|
||||
def backward(self, speed = None):
|
||||
"""Spin axis backward at given speed (0-255)
|
||||
|
@ -490,7 +494,7 @@ class axisClass:
|
|||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_REVERSE, int(speed)] )
|
||||
p.send()
|
||||
else:
|
||||
raise RepRapError("Invalid speed value")
|
||||
raise _RepRapError("Invalid speed value")
|
||||
|
||||
def getSensors(self):
|
||||
"""Debug only. Returns raw PIC port bytes)"""
|
||||
|
@ -518,7 +522,7 @@ class axisClass:
|
|||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOS, posMSB, posLSB] )
|
||||
p.send()
|
||||
else:
|
||||
raise RepRapError("Invalid position value")
|
||||
raise _RepRapError("Invalid position value")
|
||||
|
||||
def free(self):
|
||||
"""Power off coils on stepper"""
|
||||
|
@ -562,7 +566,7 @@ class axisClass:
|
|||
if not notif.dataBytes[0] == CMD_SEEK:
|
||||
raise _RepRapError("Expected seek notification")
|
||||
else:
|
||||
raise RepRapError("Invalid speed or position value")
|
||||
raise _RepRapError("Invalid speed or position value")
|
||||
|
||||
def homeReset(self, speed = None, waitArrival = True):
|
||||
"""Go to 0 position. If waitArrival is True, funtion waits until reset is compete to return"""
|
||||
|
@ -578,7 +582,7 @@ class axisClass:
|
|||
if not notif.dataBytes[0] == CMD_HOMERESET:
|
||||
raise _RepRapError("Expected home reset notification")
|
||||
else:
|
||||
raise RepRapError("Invalid speed value")
|
||||
raise _RepRapError("Invalid speed value")
|
||||
|
||||
def setNotify(self):
|
||||
"""Set axis to notify on arrivals"""
|
||||
|
@ -591,7 +595,7 @@ class axisClass:
|
|||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SYNC, int(syncMode)] )
|
||||
p.send()
|
||||
else:
|
||||
raise RepRapError("Invalid sync mode")
|
||||
raise _RepRapError("Invalid sync mode")
|
||||
|
||||
def _DDA( self, seekTo, slaveDelta, speed = False, waitArrival = True):
|
||||
"""Set DDA mode"""
|
||||
|
@ -611,17 +615,18 @@ class axisClass:
|
|||
"""Set stepper motor power (0-100%)"""
|
||||
power = int( float(power) * 0.63 )
|
||||
if power >=0 and power <=0x3F:
|
||||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, int( power * 0.63 )] ) # This is a value from 0 to 63 (6 bits)
|
||||
#p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, int( power * 0.63 )] ) # This is a value from 0 to 63 (6 bits)
|
||||
p = snap.Packet( self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, power] ) # This is a value from 0 to 63 (6 bits)
|
||||
p.send()
|
||||
else:
|
||||
raise RepRapError("Invalid power value")
|
||||
raise _RepRapError("Invalid power value")
|
||||
|
||||
def setSpeed(self, speed):
|
||||
"""Set axis move speed (0-255)"""
|
||||
if speed >= 0 and speed <= 0xFF:
|
||||
self.speed = speed
|
||||
else:
|
||||
raise RepRapError("Invalid speed value")
|
||||
raise _RepRapError("Invalid speed value")
|
||||
|
||||
def setStepsPerMM(self, spmm):
|
||||
"""Set axis steps per millimeter"""
|
||||
|
@ -667,12 +672,17 @@ class cartesianClass:
|
|||
if not waitArrival:
|
||||
print "WARNING : Reseting all axies at the same time is unstable. suggest using waitArrival = True option."
|
||||
#z is done first so we don't break anything we just made
|
||||
if self.z.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "Z Reset"
|
||||
if self.x.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "X Reset"
|
||||
if self.y.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "Y Reset"
|
||||
if self.z.active:
|
||||
if self.z.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "Z Reset"
|
||||
|
||||
if self.x.active:
|
||||
if self.x.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "X Reset"
|
||||
|
||||
if self.y.active:
|
||||
if self.y.homeReset( speed = speed, waitArrival = waitArrival ):
|
||||
print "Y Reset"
|
||||
|
||||
# TODO add a way to collect all three notifications (in whatever order) then check they are all there. this will allow symultanious axis movement and use of waitArrival
|
||||
# This requires snap receiver to search packets rather than just returning oldest one. probably need to do this anyway
|
||||
|
@ -756,21 +766,36 @@ class cartesianClass:
|
|||
|
||||
def stop(self):
|
||||
"""Stop all motors (but retain current)"""
|
||||
self.x.forward(0)
|
||||
self.y.forward(0)
|
||||
self.z.forward(0)
|
||||
if self.x.active:
|
||||
self.x.forward(0)
|
||||
|
||||
if self.y.active:
|
||||
self.y.forward(0)
|
||||
|
||||
if self.z.active:
|
||||
self.z.forward(0)
|
||||
|
||||
def free(self):
|
||||
"""Free all motors (no current on coils)"""
|
||||
self.x.free()
|
||||
self.y.free()
|
||||
self.z.free()
|
||||
if self.x.active:
|
||||
self.x.free()
|
||||
|
||||
if self.y.active:
|
||||
self.y.free()
|
||||
|
||||
if self.z.active:
|
||||
self.z.free()
|
||||
|
||||
def setPower(self, power):
|
||||
"""Set stepper power (0-100)"""
|
||||
self.x.setPower(power)
|
||||
self.y.setPower(power)
|
||||
self.z.setPower(power)
|
||||
if self.x.active:
|
||||
self.x.setPower(power)
|
||||
|
||||
if self.y.active:
|
||||
self.y.setPower(power)
|
||||
|
||||
if self.z.active:
|
||||
self.z.setPower(power)
|
||||
|
||||
#def lockout():
|
||||
#keep sending power down commands to all board every second
|
||||
|
@ -778,9 +803,14 @@ class cartesianClass:
|
|||
def setSpeed(self, speed):
|
||||
"""Set axies move speed (0-255)"""
|
||||
self.speed = speed
|
||||
self.x.setSpeed(speed)
|
||||
self.y.setSpeed(speed)
|
||||
self.z.setSpeed(speed)
|
||||
if self.x.active:
|
||||
self.x.setSpeed(speed)
|
||||
|
||||
if self.y.active:
|
||||
self.y.setSpeed(speed)
|
||||
|
||||
if self.z.active:
|
||||
self.z.setSpeed(speed)
|
||||
|
||||
def setStepsPerMM(self, spmm):
|
||||
"""Set axies steps per millimeter"""
|
||||
|
|
|
@ -167,10 +167,10 @@ def circleStroke(x1, y1, x2, y2, radius, resolution, fillDensity = False ):
|
|||
# reversing these point lets locus be drawn in one continual motion
|
||||
poly.addPoint( toolpath.Point(x2 - rsintheta, y2 + rcostheta) )
|
||||
poly.addPoint( toolpath.Point(x1 - rsintheta, y1 + rcostheta) )
|
||||
poly.addPolygon( arc(x1, y1, r, theta + startOffset, theta + endOffset, resolution, fillDensity = False) )
|
||||
poly.addPolygon( arc(x1, y1, r, theta + startOffset, theta + endOffset, resolution) )
|
||||
poly.addPoint( toolpath.Point(x1 + rsintheta, y1 - rcostheta) )
|
||||
poly.addPoint( toolpath.Point(x2 + rsintheta, y2 - rcostheta) )
|
||||
poly.addPolygon( arc(x2, y2, r, theta - startOffset, theta - endOffset, resolution, fillDensity = False) )
|
||||
poly.addPolygon( arc(x2, y2, r, theta - startOffset, theta - endOffset, resolution) )
|
||||
return poly
|
||||
|
||||
def fill(polygon, fillDensity):
|
||||
|
|
|
@ -23,6 +23,7 @@ along with pyRepRap. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
import serial, exceptions, threading, time
|
||||
from __init__ import _RepRapError
|
||||
|
||||
|
||||
SYNC_BYTE = 0x54
|
||||
|
@ -44,7 +45,7 @@ def openSerial( port = 0, rate = 19200, tout = 60 ):
|
|||
try:
|
||||
serialPort = serial.Serial( port, rate, timeout = tout )
|
||||
except:
|
||||
raise RepRapError("You do not have permissions to use the serial port, try running as root")
|
||||
raise _RepRapError("You do not have permissions to use the serial port, try running as root")
|
||||
|
||||
|
||||
def closeSerial():
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
"""
|
||||
This module contains the classed used for internal storage of toolpath instructions.
|
||||
The module can also import/export Intermediate Toolpath Language (ITL) files
|
||||
which are pyRepRap's native file format.
|
||||
"""
|
||||
|
||||
# Python module properties
|
||||
__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)"
|
||||
__license__ = "GPL 3.0"
|
||||
__licence__ = """
|
||||
pyRepRap 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.
|
||||
|
||||
pyRepRap 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 pyRepRap. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import xml.dom.minidom
|
||||
from xml.dom.minidom import Node
|
||||
|
||||
|
||||
# Point within a polygon
|
||||
class Point:
|
||||
def __init__(self, x = None, y = None, z = None):
|
||||
self.x, self.y, self.z = x, y, z
|
||||
|
||||
# Polygon within a layer
|
||||
class Polygon:
|
||||
def __init__(self, index = None, points = None, closed = False, clone = None, offsetX = 0, offsetY = 0, scale = 1, tool = None, material = None):
|
||||
if points != None:
|
||||
self.points = points
|
||||
else:
|
||||
self.points = []
|
||||
self.index = index
|
||||
self.closed = closed
|
||||
self.clone = clone
|
||||
self.offsetX = offsetX
|
||||
self.offsetY = offsetY
|
||||
self.scale = scale
|
||||
self.pointsPlotted = 0
|
||||
self.tool = tool
|
||||
self.material = material
|
||||
self.pointsPlotted = 0
|
||||
|
||||
def addPoint(self, point):
|
||||
self.points.append(point)
|
||||
|
||||
def addPoints(self, points):
|
||||
self.points += points
|
||||
|
||||
def addPolygon(self, poly):
|
||||
self.points += poly.points
|
||||
|
||||
# Layer within a toolpath
|
||||
class Layer:
|
||||
def __init__(self, index = None, polygons = None, workingHeight = None, idleHeight = None):
|
||||
self.index = index
|
||||
if polygons != None:
|
||||
self.polygons = polygons
|
||||
else:
|
||||
self.polygons = []
|
||||
self.workingHeight = workingHeight
|
||||
self.idleHeight = idleHeight
|
||||
|
||||
# Toolpath object - describes full parameters for machine build
|
||||
class Object:
|
||||
def __init__(self, layers = None, scale = 1):
|
||||
if layers != None:
|
||||
self.layers = layers
|
||||
else:
|
||||
self.currentLayer = Layer()
|
||||
self.layers = [ self.currentLayer ]
|
||||
self.offsetX = 0
|
||||
self.offsetY = 0
|
||||
self.scale = 1
|
||||
self.version = 0.3
|
||||
self.units = "mm"
|
||||
self.debug = False
|
||||
|
||||
# Read toolpath object from XML based Intermediate Toolpath Language file
|
||||
def readITL(self, filename):
|
||||
doc = xml.dom.minidom.parse(filename)
|
||||
self.layers = []
|
||||
for smilNode in doc.getElementsByTagName("ITL"):
|
||||
self.version = smilNode.getAttribute("version")
|
||||
self.layerCount = int(smilNode.getAttribute("layers"))
|
||||
self.units = smilNode.getAttribute("units")
|
||||
offset = smilNode.getAttribute("offset")
|
||||
offsetParts = offset.split(',')
|
||||
self.offsetX, self.offsetY = float(offsetParts[0]), float(offsetParts[1])
|
||||
self.scale = float(smilNode.getAttribute("scale"))
|
||||
for layerNode in smilNode.getElementsByTagName("LAYER"):
|
||||
if layerNode.getAttribute("index") == "None":
|
||||
index = None
|
||||
else:
|
||||
index = int(layerNode.getAttribute("index"))
|
||||
if layerNode.getAttribute("workingHeight") == "None":
|
||||
workingHeight = None
|
||||
else:
|
||||
workingHeight = float(layerNode.getAttribute("workingHeight"))
|
||||
if layerNode.getAttribute("idleHeight") == "None":
|
||||
idleHeight = None
|
||||
else:
|
||||
idleHeight = float(layerNode.getAttribute("idleHeight"))
|
||||
currentLayer = Layer(index, workingHeight = workingHeight, idleHeight = idleHeight)
|
||||
if self.debug: print "Layer index", index
|
||||
for polygonNode in layerNode.getElementsByTagName("POLYGON"):
|
||||
if polygonNode.getAttribute("index") == "None":
|
||||
index = None
|
||||
else:
|
||||
index = int(polygonNode.getAttribute("index"))
|
||||
if polygonNode.getAttribute("clone") == "None":
|
||||
clone = None
|
||||
else:
|
||||
clone = int(polygonNode.getAttribute("clone"))
|
||||
if polygonNode.getAttribute("closed") == "True":
|
||||
closed = True
|
||||
else:
|
||||
closed = False
|
||||
offset = polygonNode.getAttribute("offset")
|
||||
offsetParts = offset.split(',')
|
||||
offsetX, offsetY = float(offsetParts[0]), float(offsetParts[1])
|
||||
scale = float(polygonNode.getAttribute("scale"))
|
||||
if polygonNode.getAttribute("tool") == "None":
|
||||
tool = None
|
||||
else:
|
||||
tool = polygonNode.getAttribute("tool")
|
||||
if polygonNode.getAttribute("material") == "None":
|
||||
material = None
|
||||
else:
|
||||
material = polygonNode.getAttribute("material")
|
||||
if self.debug: print "Polygon index", index
|
||||
polygon = Polygon(index, closed = closed, clone = clone, offsetX = offsetX, offsetY = offsetY, scale = scale, tool = tool, material = material)
|
||||
for d in polygonNode.childNodes:
|
||||
if d.nodeType == Node.TEXT_NODE:
|
||||
lines = d.data.splitlines()
|
||||
for l in lines:
|
||||
parts = l.split('\t')
|
||||
for i in range( parts.count('') ):
|
||||
parts.remove('')
|
||||
if len(parts) > 0:
|
||||
if self.debug: print parts, parts[0][0], parts[1][0]
|
||||
if parts[0][0] == "X" and parts[1][0] == "Y":
|
||||
polygon.addPoint( Point( float(parts[0][ 1: ]), float(parts[1][ 1: ]) ) )
|
||||
if len(polygon.points):
|
||||
currentLayer.polygons.append(polygon)
|
||||
self.layers.append(currentLayer)
|
||||
|
||||
# Write toolpath object to XML based Intermediate Toolpath Language file
|
||||
def writeITL(self, filename):
|
||||
itl = '<ITL version = "0.2" layers="' + str( len(self.layers) ) + '" units="mm" offset="' + str(self.offsetX) + ',' + str(self.offsetY) + '" scale="' + str(self.scale) + '">\n'
|
||||
for layer in self.layers:
|
||||
# Index starts at one as zero is used in clone to mean not clone
|
||||
itl += '\t<LAYER index="' + str(layer.index) + '" workingHeight="' + str(layer.workingHeight) + '" idleHeight="' + str(layer.idleHeight) + '">\n'
|
||||
for polygon in layer.polygons:
|
||||
#itl += '\t\t<TOOL name="' + toolName + '" index="0">\n'
|
||||
itl += '\t\t<POLYGON index="' + str(polygon.index) + '" clone="' + str(polygon.clone) + '" closed="' + str(polygon.closed) + '" offset="' + str(polygon.offsetX) + ',' + str(polygon.offsetY) + '" scale="' + str(polygon.scale) + '" tool="' + str(polygon.tool) + '" material="' + str(polygon.material) + '">\n'
|
||||
for pointIndex, point in enumerate(polygon.points):
|
||||
itl += '\t\t\t'
|
||||
if point.x != None:
|
||||
itl += 'X' + str(point.x) + '\t'
|
||||
if point.y != None:
|
||||
itl += 'Y' + str(point.y) + '\t'
|
||||
if point.z != None:
|
||||
itl += 'Z' + str(point.z) + '\t'
|
||||
if itl[-1] == '\t':
|
||||
itl = itl[ :-1] + '\n'
|
||||
itl += '\t\t</POLYGON>\n'
|
||||
#itl += '\t\t</TOOL>\n'
|
||||
itl += '\t</LAYER>\n'
|
||||
itl += '</ITL>\n'
|
||||
f = open(filename, 'w')
|
||||
f.write(itl)
|
||||
f.close()
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
"""
|
||||
Base classes for import, export and toolhead plugins
|
||||
"""
|
||||
|
||||
# Python module properties
|
||||
__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)"
|
||||
__license__ = "GPL 3.0"
|
||||
__licence__ = """
|
||||
pyRepRap 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.
|
||||
|
||||
pyRepRap 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 pyRepRap. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import threading, reprap
|
||||
|
||||
class ImportPlotter(threading.Thread):
|
||||
"""Base class for import plotter plugins"""
|
||||
def __init__( self, fileName, toolpath,
|
||||
feedbackHandler = False,
|
||||
arcResolution = False,
|
||||
fillDensity = 4,
|
||||
debug = False ):
|
||||
"""Create plotter plugin with filename, toolpath (reprap.toolpath.Object object), feedback handler (feedback handler object), fill density (lines / mm) and debug"""
|
||||
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
self.fileName = fileName
|
||||
self.toolpath = toolpath
|
||||
self.feedbackHandler = feedbackHandler
|
||||
self.arcResolution = arcResolution
|
||||
self.fillDensity = fillDensity
|
||||
self.debug = debug
|
||||
|
||||
self.loadPreferences()
|
||||
|
||||
def terminate(self):
|
||||
"""Tell thread to terminate ASAP (result of GUI 'Stop' button)"""
|
||||
self.alive = False
|
||||
|
||||
def run(self):
|
||||
"""Run is executed when thread is started (in new thread)
|
||||
This should be defined in derived plugin class"""
|
||||
raise NotImplementedError('Import plotter plugin must define a .run() method!')
|
||||
|
||||
def getFileLimitsXY(self):
|
||||
"""Return bounding limits of file (used for zeroing position)
|
||||
This should be defined in derived plugin class"""
|
||||
raise NotImplementedError('Import plotter plugin must define a .getFileLimitsXY() method!')
|
||||
|
||||
def loadPreferences(self):
|
||||
"""Load preferences from file
|
||||
This should be defined in derived plugin class"""
|
||||
raise NotImplementedError('Import plotter plugin must define a .loadPreferences() method!')
|
||||
|
||||
|
||||
class ExportPlotter(threading.Thread):
|
||||
"""Base class for export plotter plugins"""
|
||||
def __init__( self, toolpath, toolhead,
|
||||
feedbackHandler = False,
|
||||
outputFilename = False):
|
||||
"""Create output plotter plugin with toolpath (reprap.toolpath.Object object), toolhead (toolhead plugin object), feedback handler (feedback handler object) and output file name"""
|
||||
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
self.toolpath = toolpath
|
||||
self.feedbackHandler = feedbackHandler
|
||||
self.toolhead = toolhead
|
||||
self.toolhead.output = self
|
||||
self.outputFilename = outputFilename
|
||||
|
||||
self.loadPreferences()
|
||||
|
||||
def terminate(self):
|
||||
"""Tell thread to terminate ASAP (result of GUI 'Stop' button)"""
|
||||
self.alive = False
|
||||
if dir(self).count("feedbackHandler"):
|
||||
self.feedbackHandler.setStatus("Aborting plot...")
|
||||
|
||||
def run(self):
|
||||
"""Run is executed when thread is started (in new thread)
|
||||
This should be defined in derived plugin class"""
|
||||
raise NotImplementedError('Export plotter plugin must define a .run() method!')
|
||||
|
||||
def cartesianMove(self, x, y, z, units = reprap.UNITS_MM):
|
||||
"""Perform cartesian movement
|
||||
This should be defined in derived plugin class"""
|
||||
raise NotImplementedError('Export plotter plugin must define a .cartesianMove() method!')
|
||||
|
||||
def loadPreferences(self):
|
||||
"""Load preferences from file
|
||||
This should be defined in derived plugin class"""
|
||||
raise NotImplementedError('Export plotter plugin must define a .loadPreferences() method!')
|
||||
|
||||
|
||||
class Tool:
|
||||
"""Base class for tool plugins"""
|
||||
def __init__(self):
|
||||
"""Create tool object"""
|
||||
self.loadPreferences()
|
||||
self.toolInUse = False
|
||||
|
||||
def prepare(self):
|
||||
"""Switch on tool / prepare for use (e.g. switch on cutter)
|
||||
This should be defined in derived plugin class"""
|
||||
raise NotImplementedError('Toolhead plugin must define a .prepare() method!')
|
||||
|
||||
def idle(self):
|
||||
"""Switch off tool (e.g. switch off cutter)
|
||||
This should be defined in derived plugin class"""
|
||||
raise NotImplementedError('Toolhead plugin must define a .idle() method!')
|
||||
|
||||
def ready(self):
|
||||
"""Tool use about to start, make sure it is ready (e.g. dip paintbrush)
|
||||
This should be defined in derived plugin class"""
|
||||
raise NotImplementedError('Toolhead plugin must define a .ready() method!')
|
||||
|
||||
def start(self):
|
||||
"""Start tool use (e.g. lower cutter)
|
||||
This should be defined in derived plugin class"""
|
||||
raise NotImplementedError('Toolhead plugin must define a .start() method!')
|
||||
|
||||
def stop(self):
|
||||
"""End tool use (e.g. raise cutter)
|
||||
This should be defined in derived plugin class"""
|
||||
raise NotImplementedError('Toolhead plugin must define a .stop() method!')
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# generated by wxGlade 0.6.3 on Mon Jul 21 19:56:38 2008
|
||||
|
||||
import wx, sys, os, reprap
|
||||
|
||||
# begin wxGlade: extracode
|
||||
# end wxGlade
|
||||
|
||||
|
||||
if sys.platform=="win32":
|
||||
# Windows (taking path of this script)
|
||||
iconPath = os.path.join( os.getcwd(), "graphics" )
|
||||
else:
|
||||
# Linux
|
||||
iconPath = "/usr/share/reprap/icons/"
|
||||
|
||||
appIcon = os.path.join(iconPath, "reprap.png")
|
||||
|
||||
|
||||
class AxiesPanel(wx.Panel):
|
||||
def __init__(self, *args, **kwds):
|
||||
# begin wxGlade: AxiesPanel.__init__
|
||||
kwds["style"] = wx.TAB_TRAVERSAL
|
||||
wx.Panel.__init__(self, *args, **kwds)
|
||||
self.sizer_axies_staticbox = wx.StaticBox(self, -1, "Axies")
|
||||
self.label_1 = wx.StaticText(self, -1, "X:")
|
||||
self.slider_x = wx.Slider(self, -1, 0, 0, 10)
|
||||
self.gauge_x = wx.Gauge(self, -1, 10)
|
||||
self.button_home_x = wx.Button(self, wx.ID_HOME, "")
|
||||
self.checkbox_torque_x = wx.CheckBox(self, -1, "Torque")
|
||||
self.label_1_copy = wx.StaticText(self, -1, "Y:")
|
||||
self.slider_y = wx.Slider(self, -1, 0, 0, 10)
|
||||
self.gauge_y = wx.Gauge(self, -1, 10)
|
||||
self.button_home_y = wx.Button(self, wx.ID_HOME, "")
|
||||
self.checkbox_torque_y = wx.CheckBox(self, -1, "Torque")
|
||||
self.label_1_copy_1 = wx.StaticText(self, -1, "Z:")
|
||||
self.slider_z = wx.Slider(self, -1, 0, 0, 10)
|
||||
self.gauge_z = wx.Gauge(self, -1, 10)
|
||||
self.button_home_z = wx.Button(self, wx.ID_HOME, "")
|
||||
self.checkbox_torque_z = wx.CheckBox(self, -1, "Torque")
|
||||
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
# end wxGlade
|
||||
|
||||
def __set_properties(self):
|
||||
# begin wxGlade: AxiesPanel.__set_properties
|
||||
pass
|
||||
# end wxGlade
|
||||
|
||||
def __do_layout(self):
|
||||
# begin wxGlade: AxiesPanel.__do_layout
|
||||
sizer_9 = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_axies = wx.StaticBoxSizer(self.sizer_axies_staticbox, wx.VERTICAL)
|
||||
sizer_10 = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_3_copy_1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_4_copy_1 = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_5_copy_1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_3_copy = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_4_copy = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_5_copy = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_4 = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_5 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_3.Add(self.label_1, 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_3.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_4.Add(self.slider_x, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0)
|
||||
sizer_4.Add(self.gauge_x, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0)
|
||||
sizer_5.Add(self.button_home_x, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0)
|
||||
sizer_5.Add(self.checkbox_torque_x, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0)
|
||||
sizer_4.Add(sizer_5, 1, wx.EXPAND, 0)
|
||||
sizer_3.Add(sizer_4, 1, wx.EXPAND, 0)
|
||||
sizer_10.Add(sizer_3, 0, wx.ALL|wx.EXPAND, 5)
|
||||
sizer_3_copy.Add(self.label_1_copy, 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_3_copy.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_4_copy.Add(self.slider_y, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0)
|
||||
sizer_4_copy.Add(self.gauge_y, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0)
|
||||
sizer_5_copy.Add(self.button_home_y, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0)
|
||||
sizer_5_copy.Add(self.checkbox_torque_y, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0)
|
||||
sizer_4_copy.Add(sizer_5_copy, 1, wx.EXPAND, 0)
|
||||
sizer_3_copy.Add(sizer_4_copy, 1, wx.EXPAND, 0)
|
||||
sizer_10.Add(sizer_3_copy, 0, wx.ALL|wx.EXPAND, 5)
|
||||
sizer_3_copy_1.Add(self.label_1_copy_1, 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_3_copy_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_4_copy_1.Add(self.slider_z, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0)
|
||||
sizer_4_copy_1.Add(self.gauge_z, 0, wx.EXPAND|wx.FIXED_MINSIZE, 0)
|
||||
sizer_5_copy_1.Add(self.button_home_z, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0)
|
||||
sizer_5_copy_1.Add(self.checkbox_torque_z, 1, wx.ADJUST_MINSIZE|wx.FIXED_MINSIZE, 0)
|
||||
sizer_4_copy_1.Add(sizer_5_copy_1, 1, wx.EXPAND, 0)
|
||||
sizer_3_copy_1.Add(sizer_4_copy_1, 1, wx.EXPAND, 0)
|
||||
sizer_10.Add(sizer_3_copy_1, 0, wx.ALL|wx.EXPAND, 5)
|
||||
sizer_axies.Add(sizer_10, 1, wx.ALL|wx.EXPAND, 10)
|
||||
sizer_9.Add(sizer_axies, 1, wx.ALL|wx.EXPAND, 10)
|
||||
self.SetSizer(sizer_9)
|
||||
sizer_9.Fit(self)
|
||||
# end wxGlade
|
||||
|
||||
# end of class AxiesPanel
|
||||
|
||||
|
||||
class MovePanel(wx.Panel):
|
||||
def __init__(self, *args, **kwds):
|
||||
# begin wxGlade: MovePanel.__init__
|
||||
kwds["style"] = wx.TAB_TRAVERSAL
|
||||
wx.Panel.__init__(self, *args, **kwds)
|
||||
self.sizer_buttonMove_staticbox = wx.StaticBox(self, -1, "X-Y Move")
|
||||
self.button_up = wx.BitmapButton(self, -1, (wx.Bitmap( os.path.join(iconPath, 'go-up.png'))))
|
||||
self.button_left = wx.BitmapButton(self, -1, (wx.Bitmap( os.path.join(iconPath, 'go-previous.png'))))
|
||||
self.button_right = wx.BitmapButton(self, -1, (wx.Bitmap( os.path.join(iconPath, 'go-next.png'))))
|
||||
self.button_down = wx.BitmapButton(self, -1, (wx.Bitmap( os.path.join(iconPath, 'go-down.png'))))
|
||||
self.label_2 = wx.StaticText(self, -1, "Speed :")
|
||||
self.slider_speed = wx.Slider(self, -1, 0, 0, 255, style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|wx.SL_LABELS)
|
||||
self.label_2_copy = wx.StaticText(self, -1, "Steps :")
|
||||
self.slider_steps = wx.Slider(self, -1, 0, 0, 1000, style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|wx.SL_LABELS)
|
||||
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
|
||||
self.Bind(wx.EVT_BUTTON, self.onClickUp, self.button_up)
|
||||
self.Bind(wx.EVT_BUTTON, self.onClickLeft, self.button_left)
|
||||
self.Bind(wx.EVT_BUTTON, self.onClickRight, self.button_right)
|
||||
self.Bind(wx.EVT_BUTTON, self.onClickDown, self.button_down)
|
||||
# end wxGlade
|
||||
|
||||
def __set_properties(self):
|
||||
# begin wxGlade: MovePanel.__set_properties
|
||||
self.button_up.SetSize(self.button_up.GetBestSize())
|
||||
self.button_left.SetSize(self.button_left.GetBestSize())
|
||||
self.button_right.SetSize(self.button_right.GetBestSize())
|
||||
self.button_down.SetSize(self.button_down.GetBestSize())
|
||||
# end wxGlade
|
||||
|
||||
def __do_layout(self):
|
||||
# begin wxGlade: MovePanel.__do_layout
|
||||
sizer_8 = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_buttonMove = wx.StaticBoxSizer(self.sizer_buttonMove_staticbox, wx.VERTICAL)
|
||||
sizer_8_copy = wx.BoxSizer(wx.VERTICAL)
|
||||
grid_sizer_2 = wx.FlexGridSizer(2, 2, 10, 10)
|
||||
grid_sizer_1 = wx.GridSizer(4, 3, 0, 0)
|
||||
grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add(self.button_up, 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add(self.button_left, 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add(self.button_right, 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add(self.button_down, 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_8_copy.Add(grid_sizer_1, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 30)
|
||||
grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.slider_speed, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.label_2_copy, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.slider_steps, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.AddGrowableCol(1)
|
||||
sizer_8_copy.Add(grid_sizer_2, 0, wx.EXPAND, 0)
|
||||
sizer_buttonMove.Add(sizer_8_copy, 1, wx.ALL|wx.EXPAND, 10)
|
||||
sizer_8.Add(sizer_buttonMove, 1, wx.ALL|wx.EXPAND, 10)
|
||||
self.SetSizer(sizer_8)
|
||||
sizer_8.Fit(self)
|
||||
# end wxGlade
|
||||
|
||||
|
||||
def onClickUp(self, event): # wxGlade: MovePanel.<event_handler>
|
||||
x, y, z = reprap.cartesian.getPos()
|
||||
reprap.cartesian.seek( ( None, y + int( self.slider_steps.GetValue() ), None ), waitArrival = True, speed = int( self.slider_speed.GetValue() ) )
|
||||
|
||||
def onClickLeft(self, event): # wxGlade: MovePanel.<event_handler>
|
||||
x, y, z = reprap.cartesian.getPos()
|
||||
reprap.cartesian.seek( ( x - int( self.slider_steps.GetValue() ), None, None ), waitArrival = True, speed = int( self.slider_speed.GetValue() ) )
|
||||
|
||||
def onClickRight(self, event): # wxGlade: MovePanel.<event_handler>
|
||||
x, y, z = reprap.cartesian.getPos()
|
||||
reprap.cartesian.seek( ( x + int( self.slider_steps.GetValue() ), None, None ), waitArrival = True, speed = int( self.slider_speed.GetValue() ) )
|
||||
|
||||
def onClickDown(self, event): # wxGlade: MovePanel.<event_handler>
|
||||
x, y, z = reprap.cartesian.getPos()
|
||||
reprap.cartesian.seek( ( None, y - int( self.slider_steps.GetValue() ), None ), waitArrival = True, speed = int( self.slider_speed.GetValue() ) )
|
||||
|
||||
# end of class MovePanel
|
||||
|
||||
|
||||
class MainControlFrame(wx.Frame):
|
||||
def __init__(self, *args, **kwds):
|
||||
# begin wxGlade: MainControlFrame.__init__
|
||||
kwds["style"] = wx.DEFAULT_FRAME_STYLE
|
||||
wx.Frame.__init__(self, *args, **kwds)
|
||||
self.panel_main = wx.Panel(self, -1)
|
||||
|
||||
# Tool Bar
|
||||
self.frame_main_toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL|wx.TB_TEXT|wx.TB_NOICONS)
|
||||
self.SetToolBar(self.frame_main_toolbar)
|
||||
self.frame_main_toolbar.AddLabelTool(100, "Home Reset", wx.NullBitmap, wx.NullBitmap, wx.ITEM_NORMAL, "", "")
|
||||
self.frame_main_toolbar.AddLabelTool(101, "Torque", wx.NullBitmap, wx.NullBitmap, wx.ITEM_CHECK, "", "")
|
||||
# Tool Bar end
|
||||
self.panel_axies = AxiesPanel(self.panel_main, -1)
|
||||
self.panel_move = MovePanel(self.panel_main, -1)
|
||||
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
|
||||
self.Bind(wx.EVT_TOOL, self.onClickHomeResetAll, id=100)
|
||||
self.Bind(wx.EVT_TOOL, self.onTorqueAllToggle, id=101)
|
||||
# end wxGlade
|
||||
|
||||
def __set_properties(self):
|
||||
# begin wxGlade: MainControlFrame.__set_properties
|
||||
self.SetTitle("RepRap Control")
|
||||
self.frame_main_toolbar.Realize()
|
||||
# end wxGlade
|
||||
|
||||
def __do_layout(self):
|
||||
# begin wxGlade: MainControlFrame.__do_layout
|
||||
sizer_main = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_1.Add(self.panel_axies, 1, wx.EXPAND, 0)
|
||||
sizer_1.Add(self.panel_move, 1, wx.EXPAND, 0)
|
||||
self.panel_main.SetSizer(sizer_1)
|
||||
sizer_main.Add(self.panel_main, 1, wx.EXPAND, 0)
|
||||
self.SetSizer(sizer_main)
|
||||
sizer_main.Fit(self)
|
||||
self.Layout()
|
||||
# end wxGlade
|
||||
|
||||
|
||||
def onTorqueAllToggle(self, event): # wxGlade: MainControlFrame.<event_handler>
|
||||
print "Event handler `onTorqueAllToggle' not implemented!"
|
||||
event.Skip()
|
||||
|
||||
def onClickHomeResetAll(self, event): # wxGlade: MainControlFrame.<event_handler>
|
||||
reprap.cartesian.homeReset(waitArrival = True)
|
||||
reprap.cartesian.free()
|
||||
|
||||
# end of class MainControlFrame
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
"""
|
||||
RepRap plugins system. All plugins are accessed though this module.
|
||||
"""
|
||||
|
||||
# Python module properties
|
||||
__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)"
|
||||
__license__ = "GPL 3.0"
|
||||
__licence__ = """
|
||||
pyRepRap 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.
|
||||
|
||||
pyRepRap 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 pyRepRap. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import os, sys
|
||||
|
||||
# All modules used by plugins must be imported here to ensure inclusion in py2exe build
|
||||
import replath.preferences, replath.baseplotters, wx.wizard
|
||||
|
||||
PLUGIN_IMPORT = 1
|
||||
PLUGIN_OUTPUT = 2
|
||||
PLUGIN_TOOLHEAD = 3
|
||||
#print "OSP='" + sys.platform + "'"
|
||||
|
||||
if sys.platform == "win32":
|
||||
# Windows
|
||||
print "winp"
|
||||
pluginsPath = os.path.join( os.getcwd(), "plugins" )
|
||||
else:
|
||||
# Linux
|
||||
pluginsPath = "/usr/local/share/replath/plugins"
|
||||
|
||||
print "Plugins loading from path'" + pluginsPath + "'"
|
||||
|
||||
pluginsFolders = {PLUGIN_IMPORT:"import", PLUGIN_OUTPUT:"output", PLUGIN_TOOLHEAD:"toolhead"}
|
||||
|
||||
def loadPlugins(pluginsFolder, suffix):
|
||||
oldDir = os.getcwd()
|
||||
os.chdir(pluginsFolder)
|
||||
sys.path.append(pluginsFolder)
|
||||
plugins = []
|
||||
files = os.listdir(pluginsFolder)
|
||||
for p in files:
|
||||
if p[ -len(suffix): ] == suffix:
|
||||
newPlugin = __import__( p[ :-3 ] )
|
||||
plugins.append(newPlugin)
|
||||
print "Loading plugin '" + newPlugin.Title + "' from file '" + p + "'"
|
||||
os.chdir(oldDir)
|
||||
sys.path.remove(pluginsFolder)
|
||||
return plugins
|
||||
|
||||
"""
|
||||
def getPluginsList(pluginType):
|
||||
plugins = loadPlugins( os.path.join( pluginsPath, pluginsFolders[pluginType] ), "_" + pluginsFolders[pluginType] + ".py")
|
||||
pluginList = []
|
||||
for p in plugins:
|
||||
pluginList.append(p.Title)
|
||||
return pluginList
|
||||
"""
|
||||
|
||||
def getPlugin(pluginType, index):
|
||||
plugins = loadPlugins( os.path.join( pluginsPath, pluginsFolders[pluginType] ), "_" + pluginsFolders[pluginType] + ".py")
|
||||
return plugins[index]
|
||||
|
||||
def getPlugins(pluginType):
|
||||
return loadPlugins( os.path.join( pluginsPath, pluginsFolders[pluginType] ), "_" + pluginsFolders[pluginType] + ".py")
|
||||
|
||||
def listTitles(plugins):
|
||||
pluginList = []
|
||||
for p in plugins:
|
||||
pluginList.append(p.Title)
|
||||
return pluginList
|
|
@ -0,0 +1,81 @@
|
|||
"""
|
||||
RepRap preferences system. All preferences are accessed though this module.
|
||||
"""
|
||||
|
||||
# Python module properties
|
||||
__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)"
|
||||
__license__ = "GPL 3.0"
|
||||
__licence__ = """
|
||||
pyRepRap 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.
|
||||
|
||||
pyRepRap 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 pyRepRap. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import sys, os
|
||||
|
||||
def getHomeDir():
|
||||
if sys.platform=="win32":
|
||||
return os.path.join( os.environ.get("USERPROFILE"), "Application Data" )
|
||||
else:
|
||||
return os.environ.get("HOME")
|
||||
|
||||
|
||||
class PreferenceHandler:
|
||||
# prefOwner is object from which '.pref_*' attributes will be written to / read from
|
||||
def __init__(self, prefOwner, fileName):
|
||||
if prefOwner:
|
||||
self.owner = prefOwner
|
||||
else:
|
||||
self.owner = self
|
||||
self.fileName = os.path.join( getHomeDir(), ".pyRepRap", fileName )
|
||||
|
||||
# Save preferences to file
|
||||
def save(self):
|
||||
fileText = ""
|
||||
for a in dir(self.owner):
|
||||
if a[ :5 ] == "pref_":
|
||||
#print "Preference", a, "=", getattr(self.owner, a)
|
||||
attr = getattr(self.owner, a) # Get attribute (object)
|
||||
fileText += a + '\t' + str( attr ) + '\t' + str( type(attr) )[ 7:-2 ] + '\n' # Output line format: [Pref name] [Pref Value] [Pref Type]
|
||||
|
||||
f = open(self.fileName, 'w')
|
||||
f.write(fileText)
|
||||
f.close()
|
||||
|
||||
# Load preferences from file
|
||||
def load(self):
|
||||
if not os.path.exists(self.fileName):
|
||||
print "Preference file '" + self.fileName + "' does not exist, creating"
|
||||
# If preferences directory does not exist then create it
|
||||
dirPath = os.path.join( getHomeDir(), ".pyRepRap" )
|
||||
if not os.path.exists(dirPath):
|
||||
os.mkdir(dirPath)
|
||||
self.save()
|
||||
|
||||
f = open(self.fileName, 'r')
|
||||
lines = f.read().split('\n')
|
||||
for r in lines:
|
||||
if len(r) > 0 and not r[ :1 ] == "#": # Check line is not blank or commented out
|
||||
pref, val, dType = tuple( r.split('\t') )
|
||||
if dType == "int":
|
||||
val = int(val)
|
||||
elif dType == "float":
|
||||
val = float(val)
|
||||
elif dType == "long":
|
||||
val = long(val)
|
||||
elif dType == "bool":
|
||||
if val == "True":
|
||||
val = True
|
||||
else:
|
||||
val = False
|
||||
setattr(self.owner, pref, val)
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
"""
|
||||
This module provides a pyGame surface as a wxPython object.
|
||||
I.e. it lets you use pyGame within a wx frame.
|
||||
|
||||
Code derived / inspired from a vague combination of :
|
||||
|
||||
BufferedCanvas -- Double-buffered, flicker-free canvas widget
|
||||
Copyright (C) 2005, 2006 Daniel Keep
|
||||
(GNU Lesser General Public License)
|
||||
|
||||
and
|
||||
|
||||
wxPython wiki : http://wiki.wxpython.org/IntegratingPyGame (Assumed GNU compatible)
|
||||
|
||||
and some work of my own.
|
||||
|
||||
|
||||
Example :
|
||||
|
||||
import wxpygame
|
||||
class DrawCanvas(wxpygame.wxSDLPanel):
|
||||
def __init__( self, parent, ID=-1 ):
|
||||
wxpygame.wxSDLPanel.__init__( self, parent,ID )
|
||||
|
||||
def draw(self):
|
||||
surface = self.getSurface()
|
||||
if not surface is None:
|
||||
pygame.draw.circle( surface, (250, 0, 0), (100, 100), 50 )
|
||||
pygame.display.flip()
|
||||
|
||||
"""
|
||||
|
||||
# Python module properties
|
||||
__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)"
|
||||
__license__ = "GPL 3.0"
|
||||
__credits__ = "Daniel Keep for his wx BufferedCanvas that showed me how to make a pyGame wx canvas"
|
||||
__licence__ = """
|
||||
pyRepRap 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.
|
||||
|
||||
pyRepRap 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 pyRepRap. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import wx, pygame, os, sys
|
||||
|
||||
class wxSDLPanel(wx.Panel):
|
||||
buffer = None
|
||||
backbuffer = None
|
||||
def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.NO_FULL_REPAINT_ON_RESIZE):
|
||||
wx.Panel.__init__(self,parent,ID,pos,size,style)
|
||||
self.initialized = False
|
||||
self.resized = False
|
||||
self._surface = None
|
||||
self.needsDrawing = True
|
||||
self.Bind(wx.EVT_SIZE, self.OnSize)
|
||||
self.Bind(wx.EVT_MOTION, self.MouseMove)
|
||||
self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
|
||||
self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
|
||||
self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
|
||||
self.Bind(wx.EVT_IDLE, self.OnIdle)
|
||||
|
||||
def OnIdle(self, ev):
|
||||
if not self.initialized or self.resized:
|
||||
if not self.initialized:
|
||||
# get the handle
|
||||
hwnd = self.GetHandle()
|
||||
|
||||
os.environ['SDL_WINDOWID'] = str(hwnd)
|
||||
if sys.platform == 'win32':
|
||||
os.environ['SDL_VIDEODRIVER'] = 'windib'
|
||||
|
||||
pygame.init()
|
||||
|
||||
|
||||
self.initialized = True
|
||||
else:
|
||||
self.resized = False
|
||||
x,y = self.GetSizeTuple()
|
||||
self._surface = pygame.display.set_mode((x,y))
|
||||
|
||||
if self.needsDrawing:
|
||||
self.draw()
|
||||
|
||||
"""for event in pygame.event.get():
|
||||
if (event.type == pygame.QUIT):
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
elif (event.type == pygame.MOUSEMOTION):
|
||||
self.MouseMove()
|
||||
elif (event.type == pygame.MOUSEBUTTONDOWN):
|
||||
print "md pygame"
|
||||
self.OnMouseDown()
|
||||
elif (event.type == pygame.MOUSEBUTTONUP):
|
||||
self.OnMouseUp()
|
||||
"""
|
||||
|
||||
def OnPaint(self, ev):
|
||||
self.needsDrawing = True
|
||||
|
||||
def OnSize(self, ev):
|
||||
self.resized = True
|
||||
|
||||
def draw(self):
|
||||
raise NotImplementedError('please define a .draw() method!')
|
||||
|
||||
def getSurface(self):
|
||||
return self._surface
|
||||
|
||||
def update(self):
|
||||
self.Refresh()
|
||||
print "r"
|
||||
|
||||
#def getSize(self):
|
||||
# return self.w, self.h
|
||||
|
||||
def MouseMove(self, event):
|
||||
raise NotImplementedError('please define a .MouseMove() method!')
|
||||
def OnMouseDown(self, event):
|
||||
raise NotImplementedError('please define a .OnMouseDown() method!')
|
||||
def OnMouseUp(self, event):
|
||||
raise NotImplementedError('please define a .OnMouseUp() method!')
|
||||
def OnMouseWheel(self, event):
|
||||
raise NotImplementedError('please define a .OnMouseWheel() method!')
|
||||
|
||||
|
||||
#pygame.display.quit()
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,867 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
__author__ = "Stefan Blanke (greenarrow) (greenarrow@users.sourceforge.net)"
|
||||
__credits__ = ""
|
||||
__license__ = "GPL 3.0"
|
||||
__version__ = "0.8"
|
||||
__licence__ = """
|
||||
pyRepRap 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.
|
||||
|
||||
pyRepRap 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 pyRepRap. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
# generated by wxGlade 0.6.1 on Wed Apr 23 11:49:08 2008
|
||||
|
||||
import wx, pygame, reprap, time, sys, os, threading
|
||||
import replath.wxpygame as wxpygame
|
||||
import reprap.shapeplotter, replath.plugins, reprap.toolpath
|
||||
import replath
|
||||
|
||||
appTitle = "RepRap Plot"
|
||||
|
||||
|
||||
plotterPlugins = replath.plugins.getPlugins(replath.plugins.PLUGIN_IMPORT)
|
||||
outputPlugins = replath.plugins.getPlugins(replath.plugins.PLUGIN_OUTPUT)
|
||||
toolheadPlugins = replath.plugins.getPlugins(replath.plugins.PLUGIN_TOOLHEAD)
|
||||
plotterList = replath.plugins.listTitles(plotterPlugins)
|
||||
outputList = replath.plugins.listTitles(outputPlugins)
|
||||
toolheadList = replath.plugins.listTitles(toolheadPlugins)
|
||||
|
||||
if sys.platform=="win32":
|
||||
# Windows (taking path of this script)
|
||||
iconPath = os.path.join( os.getcwd(), "graphics" )
|
||||
else:
|
||||
# Linux
|
||||
iconPath = "/usr/local/share/replath/icons/"
|
||||
|
||||
appIcon = os.path.join(iconPath, "reprap.png")
|
||||
|
||||
|
||||
|
||||
# Feedback action definitions
|
||||
EVT_FBM_ID = wx.NewId()
|
||||
FB_STATUS = 1
|
||||
FB_COMPLETE = 2
|
||||
FB_ABORTED = 3
|
||||
FB_MESSAGE = 4
|
||||
|
||||
# Feedback message event object. Always used by feedbackmessagehandler (external plotters do not use it)
|
||||
class FeedbackMessageEvent(wx.PyEvent):
|
||||
"""Simple event to carry arbitrary result data."""
|
||||
def __init__(self, action, data):
|
||||
"""Init Result Event."""
|
||||
wx.PyEvent.__init__(self)
|
||||
self.SetEventType(EVT_FBM_ID)
|
||||
self.action = action
|
||||
self.data = data
|
||||
|
||||
# Passed to plotters so they can give feedback info to the gui (including when they are finished)
|
||||
class FeedbackMessageHandler:
|
||||
def __init__(self, parent):
|
||||
self.parent = parent
|
||||
parent.Connect(-1, -1, EVT_FBM_ID, self.onEvent)
|
||||
|
||||
def onEvent(self, event):
|
||||
if event.action == FB_STATUS:
|
||||
self.parent.setStatusBar(event.data)
|
||||
elif event.action == FB_COMPLETE:
|
||||
self.parent.plotComplete()
|
||||
elif event.action == FB_ABORTED:
|
||||
self.parent.plotAborted()
|
||||
elif event.action == FB_MESSAGE:
|
||||
dlg = wx.MessageDialog(self.parent, str(event.data) + '\n', caption = appTitle, style = wx.OK)
|
||||
#dlg = wx.MessageDialog(self.parent, 'moo\n', caption = 'moo', style = wx.OK)
|
||||
dlg.ShowModal()
|
||||
|
||||
def plotComplete(self):
|
||||
wx.PostEvent( self.parent, FeedbackMessageEvent(FB_COMPLETE, None) )
|
||||
|
||||
def setStatus(self, text):
|
||||
wx.PostEvent( self.parent, FeedbackMessageEvent(FB_STATUS, text) )
|
||||
|
||||
def setProgressPopup(self, text, progress = 0):
|
||||
#if text:
|
||||
# #show window
|
||||
# self.progressDialog.progress.SetValue(int(progress))
|
||||
#else:
|
||||
# #hide window
|
||||
pass
|
||||
|
||||
def updateProgressPopup(self, progress):
|
||||
#self.progressDialog.progress.SetValue(int(progress))
|
||||
pass
|
||||
|
||||
def showMessagePopup(self, text):
|
||||
wx.PostEvent( self.parent, FeedbackMessageEvent(FB_MESSAGE, text) )
|
||||
|
||||
def aborted(self):
|
||||
wx.PostEvent( self.parent, FeedbackMessageEvent(FB_ABORTED, None) )
|
||||
|
||||
# content of this block not found: did you rename this class?
|
||||
pass
|
||||
|
||||
# Dialog class for preferences
|
||||
class PreferencesDialog(wx.Dialog):
|
||||
def __init__(self, *args, **kwds):
|
||||
# begin wxGlade: PreferencesDialog.__init__
|
||||
kwds["style"] = wx.DEFAULT_DIALOG_STYLE
|
||||
wx.Dialog.__init__(self, *args, **kwds)
|
||||
self.notebook_main = wx.Notebook(self, -1, style=wx.NB_LEFT)
|
||||
self.panel_toolheads = wx.Panel(self.notebook_main, -1)
|
||||
self.panel_outputs = wx.Panel(self.notebook_main, -1)
|
||||
self.panel_inputs = wx.Panel(self.notebook_main, -1)
|
||||
self.panel_general = wx.Panel(self.notebook_main, -1)
|
||||
self.sizer_7_staticbox = wx.StaticBox(self, -1, "")
|
||||
self.sizer_9_staticbox = wx.StaticBox(self.panel_general, -1, "")
|
||||
self.label_8 = wx.StaticText(self.panel_general, -1, "Plot offset (mm) : ")
|
||||
self.label_9 = wx.StaticText(self.panel_general, -1, "X : ")
|
||||
self.text_offsetX = wx.TextCtrl(self.panel_general, -1, "")
|
||||
self.label_10 = wx.StaticText(self.panel_general, -1, "Y :")
|
||||
self.text_offsetY = wx.TextCtrl(self.panel_general, -1, "")
|
||||
self.label_11 = wx.StaticText(self.panel_general, -1, "Fill density (lines / mm) :")
|
||||
self.text_fillDensity = wx.TextCtrl(self.panel_general, -1, "")
|
||||
self.label_16 = wx.StaticText(self.panel_general, -1, "Circle resolution (lines / mm in c) :")
|
||||
self.text_circleResolution = wx.TextCtrl(self.panel_general, -1, "")
|
||||
self.label_1 = wx.StaticText(self.panel_general, -1, "Delay between lines (seconds) :")
|
||||
self.text_lineDelay = wx.TextCtrl(self.panel_general, -1, "")
|
||||
self.label_2 = wx.StaticText(self.panel_general, -1, "Zoom step (factor) :")
|
||||
self.text_zoomStep = wx.TextCtrl(self.panel_general, -1, "")
|
||||
self.label_3 = wx.StaticText(self.panel_general, -1, "Grid division (mm) :")
|
||||
self.text_gridDivision = wx.TextCtrl(self.panel_general, -1, "")
|
||||
self.checkbox_debug = wx.CheckBox(self.panel_general, -1, "Debug")
|
||||
self.notebook_inputs = wx.Notebook(self.panel_inputs, -1, style=wx.NB_LEFT)
|
||||
self.notebook_outputs = wx.Notebook(self.panel_outputs, -1, style=wx.NB_LEFT)
|
||||
self.notebook_toolheads = wx.Notebook(self.panel_toolheads, -1, style=wx.NB_LEFT)
|
||||
self.button_Ok = wx.Button(self, wx.ID_OK, "")
|
||||
self.button_Cancel = wx.Button(self, wx.ID_CANCEL, "")
|
||||
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
|
||||
self.Bind(wx.EVT_BUTTON, self.hanBtnOk, self.button_Ok)
|
||||
self.Bind(wx.EVT_BUTTON, self.hanBtnCancel, self.button_Cancel)
|
||||
# end wxGlade
|
||||
|
||||
def __set_properties(self):
|
||||
# begin wxGlade: PreferencesDialog.__set_properties
|
||||
self.SetTitle("RepRap Gerber Plotter - Preferences")
|
||||
_icon = wx.EmptyIcon()
|
||||
_icon.CopyFromBitmap(wx.Bitmap(appIcon))
|
||||
self.SetIcon(_icon)
|
||||
# end wxGlade
|
||||
|
||||
def __do_layout(self):
|
||||
print "panel load"
|
||||
# Dynamically load panels from plugins
|
||||
self.preferencePanels = []
|
||||
for plugin in outputPlugins:
|
||||
if dir(plugin).count('PreferencesPanel'):
|
||||
newPanel = plugin.PreferencesPanel(self.notebook_outputs)
|
||||
self.preferencePanels.append( newPanel )
|
||||
self.notebook_outputs.AddPage(newPanel, plugin.Title)
|
||||
for plugin in toolheadPlugins:
|
||||
if dir(plugin).count('PreferencesPanel'):
|
||||
newPanel = plugin.PreferencesPanel(self.notebook_toolheads)
|
||||
self.preferencePanels.append( newPanel )
|
||||
self.notebook_toolheads.AddPage(newPanel, plugin.Title)
|
||||
for plugin in plotterPlugins:
|
||||
if dir(plugin).count('PreferencesPanel'):
|
||||
newPanel = plugin.PreferencesPanel(self.notebook_inputs)
|
||||
self.preferencePanels.append( newPanel )
|
||||
self.notebook_inputs.AddPage(newPanel, plugin.Title)
|
||||
|
||||
# begin wxGlade: PreferencesDialog.__do_layout
|
||||
sizer_7 = wx.StaticBoxSizer(self.sizer_7_staticbox, wx.VERTICAL)
|
||||
sizer_5 = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_7_copy = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_4 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_2 = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_9 = wx.StaticBoxSizer(self.sizer_9_staticbox, wx.VERTICAL)
|
||||
grid_sizer_2 = wx.FlexGridSizer(7, 3, 4, 0)
|
||||
grid_sizer_1 = wx.FlexGridSizer(4, 11, 4, 0)
|
||||
grid_sizer_1.Add(self.label_8, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add(self.label_9, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add(self.text_offsetX, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add(self.label_10, 0, wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add(self.text_offsetY, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_1.AddGrowableCol(4)
|
||||
grid_sizer_1.AddGrowableCol(8)
|
||||
sizer_9.Add(grid_sizer_1, 0, wx.ALL|wx.EXPAND, 10)
|
||||
grid_sizer_2.Add(self.label_11, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.text_fillDensity, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.label_16, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.text_circleResolution, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.label_1, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.text_lineDelay, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.text_zoomStep, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.label_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.text_gridDivision, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add(self.checkbox_debug, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add((10, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
grid_sizer_2.AddGrowableCol(2)
|
||||
sizer_9.Add(grid_sizer_2, 1, wx.ALL|wx.EXPAND, 10)
|
||||
sizer_2.Add(sizer_9, 1, wx.ALL|wx.EXPAND, 10)
|
||||
self.panel_general.SetSizer(sizer_2)
|
||||
sizer_1.Add(self.notebook_inputs, 1, wx.ALL|wx.EXPAND, 10)
|
||||
self.panel_inputs.SetSizer(sizer_1)
|
||||
sizer_3.Add(self.notebook_outputs, 1, wx.ALL|wx.EXPAND, 10)
|
||||
self.panel_outputs.SetSizer(sizer_3)
|
||||
sizer_4.Add(self.notebook_toolheads, 1, wx.ALL|wx.EXPAND, 10)
|
||||
self.panel_toolheads.SetSizer(sizer_4)
|
||||
self.notebook_main.AddPage(self.panel_general, "General")
|
||||
self.notebook_main.AddPage(self.panel_inputs, "Plotter Plugins")
|
||||
self.notebook_main.AddPage(self.panel_outputs, "Output Plugins")
|
||||
self.notebook_main.AddPage(self.panel_toolheads, "Toolhead Plugins")
|
||||
sizer_5.Add(self.notebook_main, 1, wx.EXPAND, 0)
|
||||
sizer_5.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_7_copy.Add(self.button_Ok, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
|
||||
sizer_7_copy.Add(self.button_Cancel, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
|
||||
sizer_5.Add(sizer_7_copy, 0, wx.EXPAND, 0)
|
||||
sizer_7.Add(sizer_5, 1, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 16)
|
||||
self.SetSizer(sizer_7)
|
||||
sizer_7.Fit(self)
|
||||
self.Layout()
|
||||
self.Centre()
|
||||
# end wxGlade
|
||||
|
||||
|
||||
|
||||
def setPrefHandler(self, pref):
|
||||
self.preferences = pref
|
||||
|
||||
# Set values of frame control
|
||||
def setPrefValues(self):
|
||||
self.text_offsetX.SetValue( str(self.preferences.pref_plotOffsetX) )
|
||||
self.text_offsetY.SetValue( str(self.preferences.pref_plotOffsetY) )
|
||||
self.text_fillDensity.SetValue( str(self.preferences.pref_fillDensity) )
|
||||
self.text_lineDelay.SetValue( str(self.preferences.pref_lineDelay) )
|
||||
self.checkbox_debug.SetValue( self.preferences.pref_debug )
|
||||
self.text_circleResolution.SetValue( str(self.preferences.pref_circleResolution) )
|
||||
self.text_gridDivision.SetValue( str(self.preferences.pref_gridDivision) )
|
||||
self.text_zoomStep.SetValue( str(self.preferences.pref_zoomStep) )
|
||||
|
||||
def getPreferences(self):
|
||||
return self.preferences
|
||||
|
||||
# User clicked OK
|
||||
def hanBtnOk(self, event): # wxGlade: PreferencesDialog.<event_handler>
|
||||
self.preferences.pref_plotOffsetX = float( self.text_offsetX.GetValue() )
|
||||
self.preferences.pref_plotOffsetY = float( self.text_offsetY.GetValue() )
|
||||
self.preferences.pref_fillDensity = int( self.text_fillDensity.GetValue() )
|
||||
self.preferences.pref_lineDelay = float( self.text_lineDelay.GetValue() )
|
||||
self.preferences.pref_debug = self.checkbox_debug.GetValue()
|
||||
self.preferences.pref_circleResolution = float( self.text_circleResolution.GetValue() )
|
||||
self.preferences.pref_gridDivision = float( self.text_gridDivision.GetValue() )
|
||||
self.preferences.pref_zoomStep = float( self.text_zoomStep.GetValue() )
|
||||
|
||||
for p in self.preferencePanels:
|
||||
p.savePrefValues()
|
||||
self.EndModal(wx.OK)
|
||||
|
||||
# User clicked Cancel
|
||||
def hanBtnCancel(self, event): # wxGlade: PreferencesDialog.<event_handler>
|
||||
self.preferences = False
|
||||
self.EndModal(wx.CANCEL)
|
||||
# end of class PreferencesDialog
|
||||
|
||||
"""
|
||||
# A set of lines for drawing on the screen TODO - put draw back in
|
||||
class lineSet:
|
||||
def __init__(self, parent, colour):
|
||||
self.parent = parent
|
||||
self.colour = colour
|
||||
self.clear()
|
||||
def setColour(colour):
|
||||
self.colour = colour
|
||||
self.tableChanged = True
|
||||
def addLine(self, line):
|
||||
self.lines.append(line)
|
||||
#self.parent.draw() #not ideal
|
||||
#pygame.display.flip()
|
||||
self.tableChanged = True
|
||||
def getLines(self):
|
||||
return self.lines
|
||||
def clear(self):
|
||||
self.lines = []
|
||||
self.tableChanged = True
|
||||
def hasChanged(self):
|
||||
if self.tableChanged:
|
||||
self.tableChanged = False
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
"""
|
||||
|
||||
# Class for pygame canvas
|
||||
class DrawCanvas(wxpygame.wxSDLPanel):
|
||||
def __init__( self, parent, ID=-1 ):
|
||||
wxpygame.wxSDLPanel.__init__(self, parent, ID)
|
||||
self.previewScale = 5.0
|
||||
self.offsetX, self.offsetY = 0, 0
|
||||
|
||||
self.black = 0, 0, 0
|
||||
self.white = 255, 255, 255
|
||||
self.grey = 160, 160, 160
|
||||
self.greyGreen = 170, 195, 170
|
||||
self.darkGrey = 140, 140, 140
|
||||
|
||||
self.backroundColour = self.white
|
||||
self.baseColour = 166, 211, 166
|
||||
self.gridColour = self.greyGreen
|
||||
self.previewColour = self.darkGrey
|
||||
self.plotColour = self.black
|
||||
|
||||
pygame.font.init()
|
||||
self.font = pygame.font.Font(None, 17)
|
||||
self.drawSurface = pygame.Surface( ( 0, 0 ) )
|
||||
self.drawn = False
|
||||
|
||||
self.drawRect = 0, 0, 10, 10
|
||||
|
||||
def setParent(self, parent):
|
||||
self.parent = parent
|
||||
self.fullRedraw()
|
||||
|
||||
def drawText( self, surface, x, y, text, font ):
|
||||
text = font.render( text, True, (255, 255, 255), (159, 182, 205) )
|
||||
textRect = text.get_rect()
|
||||
textRect.centerx = x
|
||||
textRect.centery = y
|
||||
surface.blit(text, textRect)
|
||||
|
||||
# Draw plot to widget
|
||||
def draw( self ):
|
||||
surface = self.getSurface()
|
||||
w, h = self.GetSizeTuple()
|
||||
if not surface is None:
|
||||
surface.fill( self.backroundColour )
|
||||
if self.drawn:
|
||||
surface.blit( self.drawSurface, (self.offsetX, -self.offsetY) )#limit region to visible - is this needed?
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
sys.exit()
|
||||
pygame.display.flip()
|
||||
|
||||
def fullRedraw(self):
|
||||
if self.parent.currentToolpath:
|
||||
fileOffsetX, fileOffsetY = self.parent.currentToolpath.offsetX, self.parent.currentToolpath.offsetY
|
||||
# Find limits
|
||||
#if len(self.polygons) > 0:
|
||||
minX, minY, maxX, maxY = 1000000, 1000000, -1000000, -1000000
|
||||
if len(self.parent.currentToolpath.layers):
|
||||
for layer in self.parent.currentToolpath.layers:
|
||||
for poly in layer.polygons:
|
||||
for p in poly.points:
|
||||
minX = min(minX, p.x + fileOffsetX)
|
||||
minY = min(minY, p.y + fileOffsetY)
|
||||
maxX = max(maxX, p.x + fileOffsetX)
|
||||
maxY = max(maxY, p.y + fileOffsetY)
|
||||
else:
|
||||
minX, minY, maxX, maxY = 0, 0, 0, 0
|
||||
border = int(self.parent.preferences.pref_gridDivision * self.previewScale / 2)
|
||||
w, h = self.GetSizeTuple()
|
||||
width, height = int(maxX * self.previewScale) + (2 * border), int(maxY * self.previewScale) + (2 *border)
|
||||
#print "wh", width, height
|
||||
if width > 0 and height > 0:
|
||||
self.drawSurface = pygame.Surface( ( width, height ) )
|
||||
self.drawRect = 0, 0, width, height
|
||||
|
||||
# Only draw if we have something to show
|
||||
#if len(self.polygons) > 0:
|
||||
# Draw background
|
||||
pygame.draw.rect( self.drawSurface, self.baseColour, self.drawRect, 0)
|
||||
# Draw grid
|
||||
for x in frange( 0, maxX, self.parent.preferences.pref_gridDivision ):
|
||||
pygame.draw.line( self.drawSurface, self.gridColour, ( int( float(x) * self.previewScale ) + border , border ), ( int( float(x) * self.previewScale ) + border , height - border ) )
|
||||
for y in frange( 0, maxY, self.parent.preferences.pref_gridDivision ):
|
||||
pygame.draw.line( self.drawSurface, self.gridColour, ( border, height - border - int( float(y) * self.previewScale ) ), ( width - border, height - border - int( float(y) * self.previewScale ) ) )
|
||||
|
||||
# Draw axis labels
|
||||
pygame.draw.line( self.drawSurface, self.black, (border, height - border), (border + 50, height - border) )
|
||||
pygame.draw.line( self.drawSurface, self.black, (border, height - border), (border, height - 50 - border ) )
|
||||
self.drawText( self.drawSurface, border + 25, height - border , "X", self.font )
|
||||
self.drawText( self.drawSurface, border, height - border - 25, "Y", self.font )
|
||||
#else:
|
||||
# # Draw blank white box
|
||||
# pygame.draw.rect( self.drawSurface, self.white, self.drawRect, 0)
|
||||
|
||||
for layer in self.parent.currentToolpath.layers:
|
||||
# Draw polygons
|
||||
for poly in layer.polygons:
|
||||
#print "plotting poly", poly, len(poly.points)
|
||||
oldX, oldY = poly.points[0].x, poly.points[0].y
|
||||
for ip, p in enumerate(poly.points[ 1: ]):
|
||||
if ip < poly.pointsPlotted:
|
||||
lineColour = self.black
|
||||
else:
|
||||
lineColour = self.previewColour
|
||||
x1, y1, x2, y2 = self.scaleRect( (oldX + fileOffsetX, oldY + fileOffsetY, p.x + fileOffsetX, p.y + fileOffsetY), self.previewScale )
|
||||
pygame.draw.line( self.drawSurface, lineColour, (x1 + border, height - y1 - border), (x2 + border, height - y2 -border) )
|
||||
oldX, oldY = p.x, p.y
|
||||
# Final line if closed
|
||||
if poly.closed:
|
||||
x, y = poly.points[0].x, poly.points[0].y
|
||||
x1, y1, x2, y2 = self.scaleRect( (oldX + fileOffsetX, oldY + fileOffsetY, x + fileOffsetX, y + fileOffsetY), self.previewScale )
|
||||
pygame.draw.line( self.drawSurface, self.previewColour, (x1 + border, height - y1 - border), (x2 + border, height - y2 -border) )
|
||||
self.drawn = True
|
||||
self.draw()
|
||||
|
||||
# Simple coordiante manipulation
|
||||
def scaleRect( self, rect, scale ):
|
||||
x1, y1, x2, y2 = rect
|
||||
scaleX = float(scale)
|
||||
scaleY = float(scale)
|
||||
return int( float(x1) * scale ), int( float(y1) * scale ), int( float(x2) * scale ), int( float(y2) * scale )
|
||||
|
||||
def offsetRect( self, rect, x, y ):
|
||||
x1, y1, x2, y2 = rect
|
||||
return x1 + x, y1 + y, x2, y2
|
||||
|
||||
def offsetLine(self, rect, x, y):
|
||||
x1, y1, x2, y2 = rect
|
||||
return x1 + x, y1 + y, x2 + x, y2 + y
|
||||
|
||||
def centreView(self, x, y):
|
||||
widthV, heightV = self.GetSizeTuple()
|
||||
null, null, widthD, heightD = self.drawRect
|
||||
self.offsetX = (widthV - widthD + x) / 2
|
||||
self.offsetY = (heightV - heightD + y) / -2
|
||||
|
||||
# Change draw offset to allow dragging of plot
|
||||
def MouseMove(self, event):
|
||||
w, h = self.GetSizeTuple()
|
||||
if event.LeftIsDown():
|
||||
x, y = event.GetPosition()
|
||||
if event.Dragging():
|
||||
self.offsetX, self.offsetY = x + self.moveDeltaX, self.moveDeltaY - y
|
||||
|
||||
# Record offsets for use in drag movement
|
||||
def OnMouseDown(self, event):
|
||||
w, h = self.GetSizeTuple()
|
||||
x, y = event.GetPosition()
|
||||
#print x, y
|
||||
self.moveDeltaX, self.moveDeltaY = self.offsetX - x, self.offsetY + y
|
||||
|
||||
def OnMouseUp(self, event):
|
||||
pass
|
||||
|
||||
# When mouse wheel moved, zoom in or out
|
||||
def OnMouseWheel(self, event):
|
||||
w, h = self.GetSizeTuple()
|
||||
centreX, centreY = w / 2, h / 2
|
||||
x, y = event.GetPosition()
|
||||
#deltaX, deltaY = centreX - x, y - centreY
|
||||
|
||||
if event.GetWheelRotation() > 0:
|
||||
self.previewScale = self.previewScale + self.parent.preferences.pref_zoomStep
|
||||
elif self.previewScale >= self.parent.preferences.pref_zoomStep:
|
||||
self.previewScale = self.previewScale - self.parent.preferences.pref_zoomStep
|
||||
self.fullRedraw()
|
||||
#null, null, widthD, heightD = self.drawRect
|
||||
#self.centreView(x - self.offsetX, h - y - self.offsetY)
|
||||
#self.centreView(100, 100)
|
||||
|
||||
|
||||
# Main frame class
|
||||
class MyFrame(wx.Frame):
|
||||
def __init__(self, *args, **kwds):
|
||||
# Create preference handler that stores preferences on itself
|
||||
self.preferences = replath.preferences.PreferenceHandler( False, "pyRepRap.conf" )
|
||||
# default values for preferences
|
||||
self.preferences.pref_plotOffsetX = 10.0
|
||||
self.preferences.pref_plotOffsetY = 10.0
|
||||
self.preferences.pref_fillDensity = 5
|
||||
self.preferences.pref_lineDelay = 0.0
|
||||
self.preferences.pref_debug = False
|
||||
self.preferences.pref_circleResolution = 3.0
|
||||
self.preferences.pref_gridDivision = 5.0
|
||||
self.preferences.pref_zoomStep = 1
|
||||
|
||||
self.preferences.load()
|
||||
|
||||
self.fileName = False
|
||||
self.currentPlotter = False
|
||||
self.currentToolpath = False
|
||||
|
||||
# begin wxGlade: MyFrame.__init__
|
||||
kwds["style"] = wx.DEFAULT_FRAME_STYLE
|
||||
wx.Frame.__init__(self, *args, **kwds)
|
||||
self.panel_1 = wx.Panel(self, -1)
|
||||
|
||||
# Menu Bar
|
||||
self.frmMain_menubar = wx.MenuBar()
|
||||
self.mnuFile = wx.Menu()
|
||||
self.mnuOpen = wx.MenuItem(self.mnuFile, 0, "&Open\tCtrl+O", "", wx.ITEM_NORMAL)
|
||||
self.mnuFile.AppendItem(self.mnuOpen)
|
||||
self.mnuFile.AppendSeparator()
|
||||
self.mnuPlot = wx.MenuItem(self.mnuFile, 2, "&Plot\tCtrl+P", "", wx.ITEM_NORMAL)
|
||||
self.mnuFile.AppendItem(self.mnuPlot)
|
||||
self.mnuFile.AppendSeparator()
|
||||
self.mnuQuit = wx.MenuItem(self.mnuFile, 1, "&Quit\tCtrl+Q", "", wx.ITEM_NORMAL)
|
||||
self.mnuFile.AppendItem(self.mnuQuit)
|
||||
self.frmMain_menubar.Append(self.mnuFile, "&File")
|
||||
wxglade_tmp_menu = wx.Menu()
|
||||
wxglade_tmp_menu.Append(10, "Pr&eferences", "", wx.ITEM_NORMAL)
|
||||
self.frmMain_menubar.Append(wxglade_tmp_menu, "&Edit")
|
||||
wxglade_tmp_menu = wx.Menu()
|
||||
self.mnuAbout = wx.MenuItem(wxglade_tmp_menu, 40, "&About", "", wx.ITEM_NORMAL)
|
||||
wxglade_tmp_menu.AppendItem(self.mnuAbout)
|
||||
self.frmMain_menubar.Append(wxglade_tmp_menu, "&Help")
|
||||
self.SetMenuBar(self.frmMain_menubar)
|
||||
# Menu Bar end
|
||||
self.frmMain_statusbar = self.CreateStatusBar(1, 0)
|
||||
|
||||
# Tool Bar
|
||||
self.frmMain_toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL|wx.TB_TEXT)
|
||||
self.SetToolBar(self.frmMain_toolbar)
|
||||
self.frmMain_toolbar.AddLabelTool(100, "Open", (wx.Bitmap( os.path.join(iconPath, 'document-open.png'), wx.BITMAP_TYPE_ANY )), wx.NullBitmap, wx.ITEM_NORMAL, "Open file", "")
|
||||
self.frmMain_toolbar.AddSeparator()
|
||||
self.frmMain_toolbar.AddLabelTool(110, "Stop", (wx.Bitmap( os.path.join(iconPath, 'media-playback-stop.png'), wx.BITMAP_TYPE_ANY )), wx.NullBitmap, wx.ITEM_NORMAL, "Stop current plotting action", "")
|
||||
self.frmMain_toolbar.AddSeparator()
|
||||
self.frmMain_toolbar.AddLabelTool(120, "Plot", (wx.Bitmap( os.path.join(iconPath, 'media-playback-start.png'), wx.BITMAP_TYPE_ANY )), wx.NullBitmap, wx.ITEM_NORMAL, "Plot to output plugin", "")
|
||||
self.frmMain_toolbar.AddSeparator()
|
||||
self.frmMain_toolbar.AddLabelTool(130, "Preferences", (wx.Bitmap( os.path.join(iconPath, 'configure.png'), wx.BITMAP_TYPE_ANY )), wx.NullBitmap, wx.ITEM_NORMAL, "", "")
|
||||
# Tool Bar end
|
||||
self.static_line_1 = wx.StaticLine(self.panel_1, -1)
|
||||
self.label_22 = wx.StaticText(self.panel_1, -1, "Output :")
|
||||
self.choice_output = wx.Choice(self.panel_1, -1, choices=[])
|
||||
self.label_23 = wx.StaticText(self.panel_1, -1, "Toolhead :")
|
||||
self.choice_toolhead = wx.Choice(self.panel_1, -1, choices=[])
|
||||
self.static_line_2 = wx.StaticLine(self.panel_1, -1)
|
||||
self.pygameCanvas = DrawCanvas(self.panel_1, -1)
|
||||
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
|
||||
self.Bind(wx.EVT_MENU, self.onClickOpen, self.mnuOpen)
|
||||
self.Bind(wx.EVT_MENU, self.onClickPlot, self.mnuPlot)
|
||||
self.Bind(wx.EVT_MENU, self.onClickQuit, self.mnuQuit)
|
||||
self.Bind(wx.EVT_MENU, self.onClickPreferences, id=10)
|
||||
self.Bind(wx.EVT_MENU, self.onClickAbout, self.mnuAbout)
|
||||
self.Bind(wx.EVT_TOOL, self.onClickOpen, id=100)
|
||||
self.Bind(wx.EVT_TOOL, self.onClickStop, id=110)
|
||||
self.Bind(wx.EVT_TOOL, self.onClickPlot, id=120)
|
||||
self.Bind(wx.EVT_TOOL, self.onClickPreferences, id=130)
|
||||
# end wxGlade
|
||||
|
||||
#self.Bind(wx.EVT_CLOSE, self.onCloseWindow)
|
||||
self.pygameCanvas.setParent(self)
|
||||
self.setStatusBar("RepRap Plot")
|
||||
|
||||
def __set_properties(self):
|
||||
# begin wxGlade: MyFrame.__set_properties
|
||||
self.SetTitle("RepRap Plotter")
|
||||
_icon = wx.EmptyIcon()
|
||||
_icon.CopyFromBitmap(wx.Bitmap(appIcon))
|
||||
self.SetIcon(_icon)
|
||||
self.SetSize((869, 579))
|
||||
self.frmMain_statusbar.SetStatusWidths([-1])
|
||||
# statusbar fields
|
||||
frmMain_statusbar_fields = ["frmMain_statusbar"]
|
||||
for i in range(len(frmMain_statusbar_fields)):
|
||||
self.frmMain_statusbar.SetStatusText(frmMain_statusbar_fields[i], i)
|
||||
self.frmMain_toolbar.SetToolBitmapSize((32, 32))
|
||||
self.frmMain_toolbar.Realize()
|
||||
# end wxGlade
|
||||
|
||||
# Load plugin names into choice lists
|
||||
self.choice_output.Append("None")
|
||||
for p in outputList:
|
||||
self.choice_output.Append(p)
|
||||
self.choice_output.SetSelection(0)
|
||||
|
||||
for p in toolheadList:
|
||||
self.choice_toolhead.Append(p)
|
||||
self.choice_toolhead.SetSelection(0)
|
||||
|
||||
def __do_layout(self):
|
||||
# begin wxGlade: MyFrame.__do_layout
|
||||
sizer_6 = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_main = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_19 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizer_main.Add(self.static_line_1, 0, wx.ALL|wx.EXPAND, 5)
|
||||
sizer_19.Add((10, 1), 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_19.Add(self.label_22, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
sizer_19.Add((10, 1), 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_19.Add(self.choice_output, 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_19.Add((20, 1), 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_19.Add(self.label_23, 0, wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0)
|
||||
sizer_19.Add((10, 1), 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_19.Add(self.choice_toolhead, 0, wx.ADJUST_MINSIZE, 0)
|
||||
sizer_main.Add(sizer_19, 0, wx.EXPAND, 0)
|
||||
sizer_main.Add(self.static_line_2, 0, wx.ALL|wx.EXPAND, 5)
|
||||
sizer_main.Add(self.pygameCanvas, 5, wx.EXPAND, 1)
|
||||
self.panel_1.SetSizer(sizer_main)
|
||||
sizer_6.Add(self.panel_1, 1, wx.EXPAND, 0)
|
||||
self.SetSizer(sizer_6)
|
||||
self.Layout()
|
||||
self.Centre()
|
||||
# end wxGlade
|
||||
|
||||
def plotComplete(self):
|
||||
self.pygameCanvas.fullRedraw()
|
||||
self.pygameCanvas.centreView(0, 0)
|
||||
self.currentPlotter.join()
|
||||
self.currentPlotter = False
|
||||
self.setStatusBar("Plot Complete")
|
||||
#dlg = wx.MessageDialog(self, "Plot Complete\n", caption = appTitle, style = wx.OK)
|
||||
#dlg.ShowModal()
|
||||
|
||||
def plotAborted(self):
|
||||
self.pygameCanvas.fullRedraw()
|
||||
if self.currentPlotter:
|
||||
self.currentPlotter.join()
|
||||
self.currentPlotter = False
|
||||
self.setStatusBar("Plot aborted")
|
||||
dlg = wx.MessageDialog(self, "Plot aborted\n", caption = appTitle, style = wx.OK)
|
||||
dlg.ShowModal()
|
||||
|
||||
# Produces strings for file formats in wx file dialog e.g. 'Gerber Files (*.pho)|*.pho'
|
||||
def dialogFilterString(self, extensions, name):
|
||||
rText = name + " ("
|
||||
for e in extensions:
|
||||
rText += '*' + e + ';'
|
||||
rText = rText[ :-1 ]
|
||||
rText += ")|"
|
||||
for e in extensions:
|
||||
rText += '*' + e + ';'
|
||||
# Removed as windows did not like having no end chr
|
||||
rText = rText[ :-1 ]
|
||||
return rText
|
||||
|
||||
def importPlot(self, fileName = False, quiet = False):
|
||||
if fileName:
|
||||
self.fileName = fileName
|
||||
else:
|
||||
self.fileName = False
|
||||
filters = ""
|
||||
allFormats = []
|
||||
# Produce strings for file formats for wx file dialog
|
||||
for p in plotterPlugins:
|
||||
filters += self.dialogFilterString( p.SupportedFileExtensions, p.FileTitle ) + '|'
|
||||
allFormats += p.SupportedFileExtensions
|
||||
# Produce all supported formats string, put it at the start of the list
|
||||
filters = self.dialogFilterString( allFormats, "All Supported Files" ) + '|' + filters
|
||||
filters = filters[ :-1 ]
|
||||
#print "ff [" + filters + "]"
|
||||
dialog = wx.FileDialog ( None, message = 'Open Gerber File', wildcard = filters, style = wx.OPEN )
|
||||
if dialog.ShowModal() == wx.ID_OK:
|
||||
self.fileName = dialog.GetPath()
|
||||
self.setStatusBar( "Opened File '" + self.fileName + "'" )
|
||||
dialog.Destroy()
|
||||
|
||||
if self.fileName or fileName:
|
||||
self.currentToolpath = reprap.toolpath.Object()
|
||||
self.currentToolpath.offsetX, self.currentToolpath.offsetY = self.preferences.pref_plotOffsetX, self.preferences.pref_plotOffsetY
|
||||
self.currentPlotter = False
|
||||
plugin = False
|
||||
cancel = False
|
||||
feedbackHandler = FeedbackMessageHandler(self)
|
||||
# Find a plugin that claims to handle files with the extension
|
||||
for p in plotterPlugins:
|
||||
# TODO - change to look for last dot not first, as it gets confused with network locations
|
||||
#(fileBaseName, fileExtension)=os.path.splitext(fileName)
|
||||
extension = self.fileName[ self.fileName.find('.'): ].lower()
|
||||
if p.SupportedFileExtensions.count( extension ) > 0:
|
||||
# # Check if the plotter has a preferences dialog and show it if it has one
|
||||
if dir(p).count('PreferencesDialog') and not quiet:
|
||||
plotPrefDialog = p.PreferencesDialog(None, -1, "")
|
||||
app.SetTopWindow(plotPrefDialog)
|
||||
if plotPrefDialog.ShowModal() == wx.OK:
|
||||
plugin = p
|
||||
else:
|
||||
cancel = True
|
||||
break
|
||||
else:
|
||||
plugin = p
|
||||
|
||||
# If a suitable plugin has been found
|
||||
if plugin:
|
||||
# Create plotter
|
||||
self.currentPlotter = plugin.plotter(self.fileName, self.currentToolpath,
|
||||
feedbackHandler = feedbackHandler,
|
||||
arcResolution = self.preferences.pref_circleResolution,
|
||||
fillDensity = self.preferences.pref_fillDensity,
|
||||
debug = self.preferences.pref_debug,
|
||||
)
|
||||
if self.currentPlotter:
|
||||
# Start plotter thread
|
||||
self.currentPlotter.start()
|
||||
elif not cancel :
|
||||
dlg = wx.MessageDialog(self, "File format unsupported\n", caption = appTitle, style = wx.OK)
|
||||
dlg.ShowModal()
|
||||
|
||||
def exportPlot(self, fileName = False):
|
||||
#self.setStatusBar( "Plotting File '" + self.fileName + "'" )
|
||||
# Use user selected output module
|
||||
if self.choice_output.GetSelection() > 0:
|
||||
outputs = [ self.choice_output.GetSelection() - 1 ]
|
||||
else:
|
||||
outputs = []
|
||||
feedbackHandler = FeedbackMessageHandler(self)
|
||||
toolhead = toolheadPlugins[ self.choice_toolhead.GetSelection() ].tool()
|
||||
outputPlotters = []
|
||||
for o in outputs:
|
||||
outputFilename = None
|
||||
if outputPlugins[o].FileOutput:
|
||||
saveDialog = wx.FileDialog(self, message='Save file as...', wildcard=outputPlugins[o].Wildcard, style=wx.SAVE | wx.OVERWRITE_PROMPT) #defaultDir=dir, defaultFile='',
|
||||
if saveDialog.ShowModal() == wx.ID_OK:
|
||||
outputFilename = saveDialog.GetPath()
|
||||
else:
|
||||
outputFilename = None
|
||||
saveDialog.Destroy()
|
||||
|
||||
self.currentPlotter = outputPlugins[o].output(self.currentToolpath, toolhead, feedbackHandler, outputFilename)
|
||||
self.currentPlotter.start()
|
||||
|
||||
|
||||
def setStatusBar(self, text):
|
||||
self.frmMain_statusbar.SetStatusText( text, 0 )
|
||||
|
||||
def onClickOpen(self, event): # wxGlade: MyFrame.<event_handler>
|
||||
if self.currentPlotter:
|
||||
dlg = wx.MessageDialog(self, "Current action must be stopped before opening a file.\n", caption = appTitle, style = wx.OK)
|
||||
dlg.ShowModal()
|
||||
else:
|
||||
self.importPlot()
|
||||
|
||||
#def onCloseWindow(self, evt):
|
||||
# #self.Destroy()
|
||||
# wx.Exit()
|
||||
|
||||
def onClickQuit(self, event): # wxGlade: MyFrame.<event_handler>
|
||||
wx.Exit()
|
||||
|
||||
def onClickPreferences(self, event): # wxGlade: MyFrame.<event_handler>
|
||||
dialogPref = PreferencesDialog(None, -1, "")
|
||||
app.SetTopWindow(dialogPref)
|
||||
|
||||
dialogPref.setPrefHandler( self.preferences )
|
||||
dialogPref.setPrefValues()
|
||||
dialogPref.ShowModal()
|
||||
|
||||
self.pygameCanvas.fullRedraw()
|
||||
|
||||
dialogPref.Destroy()
|
||||
self.preferences.save()
|
||||
|
||||
def onClickAbout(self, event): # wxGlade: MyFrame.<event_handler>
|
||||
description = "RepRap Plotter is a program for plotting Gerber and CAD files on a RepRap machine."
|
||||
info = wx.AboutDialogInfo()
|
||||
info.SetIcon(wx.Icon(appIcon, wx.BITMAP_TYPE_PNG))
|
||||
info.SetName('About RepRap Plotter')
|
||||
info.SetVersion(__version__)
|
||||
info.SetDescription(description)
|
||||
#info.SetCopyright('')
|
||||
info.SetLicence(__licence__)
|
||||
info.AddDeveloper(__author__)
|
||||
wx.AboutBox(info)
|
||||
|
||||
def onClickStop(self, event): # wxGlade: MyFrame.<event_handler>
|
||||
# tell plotter thread to quit
|
||||
if self.currentPlotter:
|
||||
self.currentPlotter.terminate()
|
||||
else:
|
||||
dlg = wx.MessageDialog(self, "Nothing is currently being plotted.\n", caption = appTitle, style = wx.OK)
|
||||
dlg.ShowModal()
|
||||
|
||||
def onClickPlot(self, event): # wxGlade: MyFrame.<event_handler>
|
||||
if self.currentPlotter:
|
||||
dlg = wx.MessageDialog(self, "Current action must be stopped before plotting.\n", caption = appTitle, style = wx.OK)
|
||||
dlg.ShowModal()
|
||||
else:
|
||||
self.exportPlot()
|
||||
|
||||
|
||||
# end of class MyFrame
|
||||
|
||||
|
||||
# Range function accepting floats (by Dinu Gherman)
|
||||
def frange(start, end=None, inc=None):
|
||||
if end == None:
|
||||
end = start + 0.0
|
||||
start = 0.0
|
||||
if inc == None:
|
||||
inc = 1.0
|
||||
L = []
|
||||
while 1:
|
||||
next = start + len(L) * inc
|
||||
if inc > 0 and next >= end:
|
||||
break
|
||||
elif inc < 0 and next <= end:
|
||||
break
|
||||
L.append(next)
|
||||
return L
|
||||
|
||||
|
||||
# Strip quotations
|
||||
def stripQuotes(text):
|
||||
if (text[0] == '"' and text[-1] == '"') or (text[0] == "'" and text[-1] == "'"):
|
||||
return text[ 1:-1 ]
|
||||
else:
|
||||
return text
|
||||
|
||||
|
||||
showGui = True
|
||||
if len(sys.argv) > 1:
|
||||
if sys.argv.count("--nogui") or sys.argv.count("--g") or sys.argv.count("--help") or sys.argv.count("-h") > 0:
|
||||
showGui = False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if showGui:
|
||||
app = wx.PySimpleApp(0)
|
||||
wx.InitAllImageHandlers()
|
||||
frmMain = MyFrame(None, -1, "")
|
||||
app.SetTopWindow(frmMain)
|
||||
frmMain.Show()
|
||||
# Command line arg plot file temp TODO proper
|
||||
|
||||
if sys.argv.count("--quiet") or sys.argv.count("--q"):
|
||||
quiet = True
|
||||
else:
|
||||
quiet = False
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
frmMain.importPlot( stripQuotes(sys.argv[-1]), quiet )
|
||||
|
||||
|
||||
app.MainLoop()
|
||||
else:
|
||||
print "TODO : Command line only mode"
|
||||
if sys.argv.count("--help"):
|
||||
print "Usage: reprapplot [OPTIONS] [FILE]..."
|
||||
print "Option GNU long option Meaning"
|
||||
print " -h --help Show this message"
|
||||
print " -g --nogui Don't show GUI"
|
||||
print " -q --quiet Don't ask questions"
|
||||
|
||||
|
||||
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 167 KiB |
|
@ -36,7 +36,7 @@ if sys.platform == "win32":
|
|||
pluginsPath = os.path.join( os.getcwd(), "plugins" )
|
||||
else:
|
||||
# Linux
|
||||
pluginsPath = "/usr/share/replath/plugins"
|
||||
pluginsPath = "/usr/local/share/replath/plugins"
|
||||
|
||||
print "Plugins loading from path'" + pluginsPath + "'"
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ if sys.platform=="win32":
|
|||
iconPath = os.path.join( os.getcwd(), "graphics" )
|
||||
else:
|
||||
# Linux
|
||||
iconPath = "/usr/share/replath/icons/"
|
||||
iconPath = "/usr/local/share/replath/icons/"
|
||||
|
||||
appIcon = os.path.join(iconPath, "reprap.png")
|
||||
|
||||
|
|
Loading…
Reference in New Issue