Commit b88342ef authored by Guillaume Seguin's avatar Guillaume Seguin

Merge branch 'experimental' of github.com:kliment/Printrun into experimental

parents 87ae561f 66c6f8d5
...@@ -63,11 +63,11 @@ class wxGLPanel(wx.Panel): ...@@ -63,11 +63,11 @@ class wxGLPanel(wx.Panel):
def processSizeEvent(self, event): def processSizeEvent(self, event):
'''Process the resize event.''' '''Process the resize event.'''
if (wx.VERSION > (2,9) and self.canvas.IsShownOnScreen()) or self.canvas.GetContext():
# Make sure the frame is shown before calling SetCurrent.
size = self.GetClientSize() size = self.GetClientSize()
self.winsize = (size.width, size.height) self.winsize = (size.width, size.height)
self.width, self.height = size.width, size.height self.width, self.height = size.width, size.height
if (wx.VERSION > (2,9) and self.canvas.IsShownOnScreen()) or self.canvas.GetContext():
# Make sure the frame is shown before calling SetCurrent.
self.canvas.SetCurrent(self.context) self.canvas.SetCurrent(self.context)
self.OnReshape(size.width, size.height) self.OnReshape(size.width, size.height)
self.canvas.Refresh(False) self.canvas.Refresh(False)
...@@ -97,11 +97,9 @@ class wxGLPanel(wx.Panel): ...@@ -97,11 +97,9 @@ class wxGLPanel(wx.Panel):
def OnInitGL(self): def OnInitGL(self):
'''Initialize OpenGL for use in the window.''' '''Initialize OpenGL for use in the window.'''
#create a pyglet context for this panel #create a pyglet context for this panel
self.mvmat = (GLdouble * 16)()
self.pygletcontext = gl.Context(gl.current_context) self.pygletcontext = gl.Context(gl.current_context)
self.pygletcontext.canvas = self self.pygletcontext.canvas = self
self.pygletcontext.set_current() self.pygletcontext.set_current()
self.dist = 1000
#normal gl init #normal gl init
glClearColor(0.98, 0.98, 0.78, 1) glClearColor(0.98, 0.98, 0.78, 1)
glClearDepth(1.0) # set depth value to 1 glClearDepth(1.0) # set depth value to 1
...@@ -121,12 +119,9 @@ class wxGLPanel(wx.Panel): ...@@ -121,12 +119,9 @@ class wxGLPanel(wx.Panel):
glViewport(0, 0, width, height) glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION) glMatrixMode(GL_PROJECTION)
glLoadIdentity() glLoadIdentity()
gluPerspective(60., width / float(height), .1, 1000.) gluPerspective(60., width / float(height), 10.0, 3 * self.dist)
glMatrixMode(GL_MODELVIEW) glMatrixMode(GL_MODELVIEW)
glLoadIdentity() glLoadIdentity()
glTranslatef(*self.transv)
glMultMatrixd(build_rotmatrix(self.basequat))
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
# Wrap text to the width of the window # Wrap text to the width of the window
if self.GLinitialized: if self.GLinitialized:
...@@ -250,7 +245,6 @@ class GcodeViewPanel(wxGLPanel): ...@@ -250,7 +245,6 @@ class GcodeViewPanel(wxGLPanel):
self.dist = max(build_dimensions[0], build_dimensions[1]) self.dist = max(build_dimensions[0], build_dimensions[1])
else: else:
self.dist = 200 self.dist = 200
self.transv = [0, 0, -self.dist]
self.basequat = [0, 0, 0, 1] self.basequat = [0, 0, 0, 1]
self.mousepos = [0, 0] self.mousepos = [0, 0]
...@@ -268,11 +262,10 @@ class GcodeViewPanel(wxGLPanel): ...@@ -268,11 +262,10 @@ class GcodeViewPanel(wxGLPanel):
'''called in the middle of ondraw after the buffer has been cleared''' '''called in the middle of ondraw after the buffer has been cleared'''
self.create_objects() self.create_objects()
glLoadIdentity()
glMultMatrixd(self.mvmat)
glPushMatrix() glPushMatrix()
glTranslatef(-self.parent.platform.width/2, -self.parent.platform.depth/2, 0) glTranslatef(0, 0, -self.dist) # Move back
glMultMatrixd(build_rotmatrix(self.basequat)) # Rotate according to trackball
glTranslatef(-self.parent.platform.width/2, -self.parent.platform.depth/2, 0) # Move origin to bottom left of platform
for obj in self.parent.objects: for obj in self.parent.objects:
if not obj.model or not obj.model.loaded or not obj.model.initialized: if not obj.model or not obj.model.loaded or not obj.model.initialized:
...@@ -304,23 +297,16 @@ class GcodeViewPanel(wxGLPanel): ...@@ -304,23 +297,16 @@ class GcodeViewPanel(wxGLPanel):
if self.initpos == None: if self.initpos == None:
self.initpos = event.GetPositionTuple() self.initpos = event.GetPositionTuple()
else: else:
#print self.initpos
p1 = self.initpos p1 = self.initpos
self.initpos = None self.initpos = None
p2 = event.GetPositionTuple() p2 = event.GetPositionTuple()
sz = self.GetClientSize() sz = self.GetClientSize()
p1x = (float(p1[0]) - sz[0] / 2) / (sz[0] / 2) p1x = float(p1[0]) / (sz[0] / 2) - 1
p1y = -(float(p1[1]) - sz[1] / 2) / (sz[1] / 2) p1y = 1 - float(p1[1]) / (sz[1] / 2)
p2x = (float(p2[0]) - sz[0] / 2) / (sz[0] / 2) p2x = float(p2[0]) / (sz[0] / 2) - 1
p2y = -(float(p2[1]) - sz[1] / 2) / (sz[1] / 2) p2y = 1 - float(p2[1]) / (sz[1] / 2)
#print p1x, p1y, p2x, p2y quat = trackball(p1x, p1y, p2x, p2y, self.dist / 250.0)
quat = trackball(p1x, p1y, p2x, p2y, -self.transv[2] / 250.0)
self.basequat = mulquat(self.basequat, quat) self.basequat = mulquat(self.basequat, quat)
mat = build_rotmatrix(self.basequat)
glLoadIdentity()
glTranslatef(*self.transv)
glMultMatrixd(mat)
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
elif event.ButtonUp(wx.MOUSE_BTN_LEFT): elif event.ButtonUp(wx.MOUSE_BTN_LEFT):
if self.initpos is not None: if self.initpos is not None:
...@@ -335,21 +321,8 @@ class GcodeViewPanel(wxGLPanel): ...@@ -335,21 +321,8 @@ class GcodeViewPanel(wxGLPanel):
else: else:
p1 = self.initpos p1 = self.initpos
p2 = event.GetPositionTuple() p2 = event.GetPositionTuple()
sz = self.GetClientSize()
p1 = list(p1) + [0]
p2 = list(p2) + [0]
p1[1] *= -1
p2[1] *= -1
sz = list(sz) + [1]
sz[0] *= 2
sz[1] *= 2
self.transv = map(lambda x, y, z, c: c - self.dist * (x - y) / z, p1, p2, sz, self.transv)
glLoadIdentity() glTranslatef(p2[0] - p1[0], -(p2[1] - p1[1]), 0)
glTranslatef(*self.transv)
glMultMatrixd(build_rotmatrix(self.basequat))
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat)
self.initpos = None self.initpos = None
else: else:
event.Skip() event.Skip()
...@@ -362,7 +335,10 @@ class GcodeViewPanel(wxGLPanel): ...@@ -362,7 +335,10 @@ class GcodeViewPanel(wxGLPanel):
return return
max_layers = self.parent.model.max_layers max_layers = self.parent.model.max_layers
current_layer = self.parent.model.num_layers_to_draw current_layer = self.parent.model.num_layers_to_draw
new_layer = min(max_layers, current_layer + 1) # accept going up to max_layers + 1
# max_layers means visualizing the last layer differently,
# max_layers + 1 means visualizing all layers with the same color
new_layer = min(max_layers + 1, current_layer + 1)
self.parent.model.num_layers_to_draw = new_layer self.parent.model.num_layers_to_draw = new_layer
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
...@@ -374,13 +350,15 @@ class GcodeViewPanel(wxGLPanel): ...@@ -374,13 +350,15 @@ class GcodeViewPanel(wxGLPanel):
self.parent.model.num_layers_to_draw = new_layer self.parent.model.num_layers_to_draw = new_layer
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
def zoom(self, dist): def zoom(self, factor, to = None):
self.transv[2] += dist
glMatrixMode(GL_MODELVIEW) glMatrixMode(GL_MODELVIEW)
glLoadIdentity() if to:
glTranslatef(*self.transv) delta_x = to[0]
glMultMatrixd(build_rotmatrix(self.basequat)) delta_y = to[1]
glGetDoublev(GL_MODELVIEW_MATRIX, self.mvmat) glTranslatef(delta_x, delta_y, 0)
glScalef(factor, factor, 1)
if to:
glTranslatef(-delta_x, -delta_y, 0)
wx.CallAfter(self.Refresh) wx.CallAfter(self.Refresh)
def wheel(self, event): def wheel(self, event):
...@@ -388,20 +366,37 @@ class GcodeViewPanel(wxGLPanel): ...@@ -388,20 +366,37 @@ class GcodeViewPanel(wxGLPanel):
without shift: set max layer without shift: set max layer
with shift: zoom viewport with shift: zoom viewport
""" """
z = event.GetWheelRotation() delta = event.GetWheelRotation()
dist = 10 factor = 1.05
if event.ShiftDown(): if event.ShiftDown():
if not self.parent.model: if not self.parent.model:
return return
if z > 0: if delta > 0:
self.layerup() self.layerup()
else: else:
self.layerdown() self.layerdown()
return return
if z > 0: x, y = event.GetPositionTuple()
self.zoom(dist) x, y, _ = self.mouse_to_3d(x, y)
if delta > 0:
self.zoom(factor, (x, y))
else: else:
self.zoom(-dist) self.zoom(1/factor, (x, y))
def mouse_to_3d(self, x, y):
x = float(x)
y = self.height - float(y)
pmat = (GLdouble * 16)()
mvmat = (GLdouble * 16)()
viewport = (GLint * 4)()
px = (GLdouble)()
py = (GLdouble)()
pz = (GLdouble)()
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_PROJECTION_MATRIX, pmat)
glGetDoublev(GL_MODELVIEW_MATRIX, mvmat)
gluUnProject(x, y, 1.0, mvmat, pmat, viewport, px, py, pz)
return (px.value, py.value, pz.value)
def keypress(self, event): def keypress(self, event):
"""gets keypress events and moves/rotates acive shape""" """gets keypress events and moves/rotates acive shape"""
......
...@@ -241,6 +241,7 @@ class GcodeModel(Model): ...@@ -241,6 +241,7 @@ class GcodeModel(Model):
color_tool0 = (1.0, 0.0, 0.0, 0.6) color_tool0 = (1.0, 0.0, 0.0, 0.6)
color_tool1 = (0.0, 0.0, 1.0, 0.6) color_tool1 = (0.0, 0.0, 1.0, 0.6)
color_printed = (0.2, 0.75, 0, 0.6) color_printed = (0.2, 0.75, 0, 0.6)
color_current = (0.6, 0.3, 0, 1)
use_vbos = True use_vbos = True
loaded = False loaded = False
...@@ -337,33 +338,56 @@ class GcodeModel(Model): ...@@ -337,33 +338,56 @@ class GcodeModel(Model):
else: else:
glVertexPointer(3, GL_FLOAT, 0, self.vertex_buffer.ptr) glVertexPointer(3, GL_FLOAT, 0, self.vertex_buffer.ptr)
if mode_2d: self.vertex_color_buffer.bind()
glScale(1.0, 1.0, 0.0) # discard z coordinates if has_vbo:
start = self.layer_stops[self.num_layers_to_draw - 1] glColorPointer(4, GL_FLOAT, 0, None)
end = self.layer_stops[self.num_layers_to_draw] - start else:
else: # 3d glColorPointer(4, GL_FLOAT, 0, self.vertex_color_buffer.ptr)
start = 0 start = 0
end = self.layer_stops[self.num_layers_to_draw] if self.num_layers_to_draw <= self.max_layers:
end_prev_layer = self.layer_stops[self.num_layers_to_draw - 1]
else:
end_prev_layer = -1
end = self.layer_stops[min(self.num_layers_to_draw, self.max_layers)]
glDisableClientState(GL_COLOR_ARRAY) glDisableClientState(GL_COLOR_ARRAY)
glColor4f(*self.color_printed) glColor4f(*self.color_printed)
printed_end = min(self.printed_until, end) # Draw printed stuff until end or end_prev_layer
if start < printed_end: cur_end = min(self.printed_until, end)
glDrawArrays(GL_LINES, start, printed_end) if end_prev_layer >= 0:
cur_end = min(cur_end, end_prev_layer)
if cur_end >= 0:
glDrawArrays(GL_LINES, start, cur_end)
glEnableClientState(GL_COLOR_ARRAY) glEnableClientState(GL_COLOR_ARRAY)
self.vertex_color_buffer.bind() # Draw nonprinted stuff until end_prev_layer
if has_vbo: start = max(cur_end, 0)
glColorPointer(4, GL_FLOAT, 0, None) if end_prev_layer >= start:
else: glDrawArrays(GL_LINES, start, end_prev_layer - start)
glColorPointer(4, GL_FLOAT, 0, self.vertex_color_buffer.ptr) cur_end = end_prev_layer
glDisableClientState(GL_COLOR_ARRAY)
glColor4f(*self.color_current)
# Draw current layer
orig_linewidth = (GLfloat)()
glGetFloatv(GL_LINE_WIDTH, orig_linewidth)
glLineWidth(2.0)
if end_prev_layer >= 0 and end > end_prev_layer:
glDrawArrays(GL_LINES, end_prev_layer, end - end_prev_layer)
glLineWidth(orig_linewidth)
glEnableClientState(GL_COLOR_ARRAY)
# Draw non printed stuff until end (if not ending at a given layer)
start = max(self.printed_until, 0) start = max(self.printed_until, 0)
end = end - start end = end - start
if start >= 0 and end > 0: if end_prev_layer < 0 and end > 0:
glDrawArrays(GL_LINES, start, end) glDrawArrays(GL_LINES, start, end)
self.vertex_buffer.unbind() self.vertex_buffer.unbind()
......
...@@ -3,8 +3,10 @@ ...@@ -3,8 +3,10 @@
import tornado.ioloop import tornado.ioloop
import tornado.web import tornado.web
import tornado.websocket import tornado.websocket
from tornado.web import asynchronous
from tornado import gen from tornado import gen
import tornado.httpserver import tornado.httpserver
import uuid
import time import time
import base64 import base64
import logging import logging
...@@ -90,12 +92,51 @@ class StopHandler(tornado.web.RequestHandler): ...@@ -90,12 +92,51 @@ class StopHandler(tornado.web.RequestHandler):
prontserve.do_stop() prontserve.do_stop()
self.finish("ACK") self.finish("ACK")
@tornado.web.stream_body
class JobsHandler(tornado.web.RequestHandler): class JobsHandler(tornado.web.RequestHandler):
def post(self): def post(self):
self.read_bytes = 0
self.total_bytes = self.request.content_length
self.body = ''
print self.request
session_uuid = self.get_argument("session_uuid", None)
print "me"
print session_uuid
print "them"
self.websocket = None
for c in ConstructSocketHandler.clients:
print c.session_uuid
if c.session_uuid == session_uuid: self.websocket = c
self.request.request_continue()
self.read_chunks()
def read_chunks(self, chunk=''):
self.read_bytes += len(chunk)
self.body += chunk
if chunk: self.process_chunk()
chunk_length = min(100000, self.request.content_length - self.read_bytes)
if chunk_length > 0:
self.request.connection.stream.read_bytes(
chunk_length, self.read_chunks)
else:
self.request._on_request_body(self.body, self.uploaded)
def process_chunk(self):
print self.get_argument("session_uuid", None)
print "bytes: (%i / %i)"%(self.read_bytes, self.total_bytes)
msg = {'uploaded': self.read_bytes, 'total': self.total_bytes}
if self.websocket != None:
self.websocket.send(job_upload_progress_changed = msg)
def uploaded(self):
fileinfo = self.request.files['job'][0] fileinfo = self.request.files['job'][0]
prontserve.do_add_job(fileinfo['filename'], fileinfo['body']) prontserve.do_add_job(fileinfo['filename'], fileinfo['body'])
self.finish("ACK") self.finish("ACK")
class JobHandler(tornado.web.RequestHandler): class JobHandler(tornado.web.RequestHandler):
def delete(self, job_id): def delete(self, job_id):
prontserve.do_rm_job(job_id) prontserve.do_rm_job(job_id)
...@@ -116,6 +157,7 @@ class InspectHandler(tornado.web.RequestHandler): ...@@ -116,6 +157,7 @@ class InspectHandler(tornado.web.RequestHandler):
#class EchoWebSocketHandler(tornado.web.RequestHandler): #class EchoWebSocketHandler(tornado.web.RequestHandler):
class ConstructSocketHandler(tornado.websocket.WebSocketHandler): class ConstructSocketHandler(tornado.websocket.WebSocketHandler):
clients = []
def on_sensor_changed(self): def on_sensor_changed(self):
for name in ['bed', 'extruder']: for name in ['bed', 'extruder']:
...@@ -141,6 +183,8 @@ class ConstructSocketHandler(tornado.websocket.WebSocketHandler): ...@@ -141,6 +183,8 @@ class ConstructSocketHandler(tornado.websocket.WebSocketHandler):
return "construct.text.0.0.1" return "construct.text.0.0.1"
def open(self): def open(self):
self.session_uuid = str(uuid.uuid4())
self.clients.append(self)
prontserve.listeners.add(self) prontserve.listeners.add(self)
self.write_message({'headers': { self.write_message({'headers': {
'jobs': prontserve.jobs.public_list(), 'jobs': prontserve.jobs.public_list(),
...@@ -151,6 +195,7 @@ class ConstructSocketHandler(tornado.websocket.WebSocketHandler): ...@@ -151,6 +195,7 @@ class ConstructSocketHandler(tornado.websocket.WebSocketHandler):
for k, v in prontserve.target_values.iteritems(): for k, v in prontserve.target_values.iteritems():
self.on_uncaught_event("target_temp_changed", {k: v}) self.on_uncaught_event("target_temp_changed", {k: v})
self.on_uncaught_event("job_progress_changed", prontserve.previous_job_progress) self.on_uncaught_event("job_progress_changed", prontserve.previous_job_progress)
self.send(initialized= {'session_uuid': self.session_uuid} )
print "WebSocket opened. %i sockets currently open." % len(prontserve.listeners) print "WebSocket opened. %i sockets currently open." % len(prontserve.listeners)
def send(self, dict_args = {}, **kwargs): def send(self, dict_args = {}, **kwargs):
...@@ -204,6 +249,7 @@ class ConstructSocketHandler(tornado.websocket.WebSocketHandler): ...@@ -204,6 +249,7 @@ class ConstructSocketHandler(tornado.websocket.WebSocketHandler):
self.write_message({"error": "%s command does not exist."%cmd}) self.write_message({"error": "%s command does not exist."%cmd})
def on_close(self): def on_close(self):
self.clients.remove(self)
prontserve.listeners.remove(self) prontserve.listeners.remove(self)
print "WebSocket closed. %i sockets currently open." % len(prontserve.listeners) print "WebSocket closed. %i sockets currently open." % len(prontserve.listeners)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment