1 from __future__ import absolute_import
11 OpenGL.ERROR_CHECKING = False
12 from OpenGL.GLU import *
13 from OpenGL.GL import *
15 from Cura.gui import printWindow
16 from Cura.util import profile
17 from Cura.util import meshLoader
18 from Cura.util import objectScene
19 from Cura.util import resources
20 from Cura.util import sliceEngine
21 from Cura.util import machineCom
22 from Cura.util import removableStorage
23 from Cura.gui.util import previewTools
24 from Cura.gui.util import opengl
25 from Cura.gui.util import openglGui
28 def __init__(self, start, end, runTime):
31 self._startTime = time.time()
32 self._runTime = runTime
35 return time.time() > self._startTime + self._runTime
37 def getPosition(self):
40 f = (time.time() - self._startTime) / self._runTime
43 #f = 6*tc*ts + -15*ts*ts + 10*tc
45 return self._start + (self._end - self._start) * f
47 class SceneView(openglGui.glGuiPanel):
48 def __init__(self, parent):
49 super(SceneView, self).__init__(parent)
54 self._scene = objectScene.Scene()
55 self._objectShader = None
57 self._selectedObj = None
58 self._objColors = [None,None,None,None]
61 self._mouseState = None
62 self._viewTarget = numpy.array([0,0,0], numpy.float32)
65 self._platformMesh = meshLoader.loadMeshes(resources.getPathForMesh('ultimaker_platform.stl'))[0]
66 self._platformMesh._drawOffset = numpy.array([0,0,1.5], numpy.float32)
67 self._isSimpleMode = True
70 self._modelMatrix = None
71 self._projMatrix = None
72 self.tempMatrix = None
74 self.openFileButton = openglGui.glButton(self, 4, 'Load', (0,0), self.ShowLoadModel)
75 self.printButton = openglGui.glButton(self, 6, 'Print', (1,0), self.ShowPrintWindow)
76 self.printButton.setDisabled(True)
79 self.rotateToolButton = openglGui.glRadioButton(self, 8, 'Rotate', (0,-1), group, self.OnToolSelect)
80 self.scaleToolButton = openglGui.glRadioButton(self, 9, 'Scale', (1,-1), group, self.OnToolSelect)
81 self.mirrorToolButton = openglGui.glRadioButton(self, 10, 'Mirror', (2,-1), group, self.OnToolSelect)
83 self.resetRotationButton = openglGui.glButton(self, 12, 'Reset', (0,-2), self.OnRotateReset)
84 self.layFlatButton = openglGui.glButton(self, 16, 'Lay flat', (0,-3), self.OnLayFlat)
86 self.resetScaleButton = openglGui.glButton(self, 13, 'Reset', (1,-2), self.OnScaleReset)
87 self.scaleMaxButton = openglGui.glButton(self, 17, 'To max', (1,-3), self.OnScaleMax)
89 self.mirrorXButton = openglGui.glButton(self, 14, 'Mirror X', (2,-2), lambda button: self.OnMirror(0))
90 self.mirrorYButton = openglGui.glButton(self, 18, 'Mirror Y', (2,-3), lambda button: self.OnMirror(1))
91 self.mirrorZButton = openglGui.glButton(self, 22, 'Mirror Z', (2,-4), lambda button: self.OnMirror(2))
93 self.rotateToolButton.setExpandArrow(True)
94 self.scaleToolButton.setExpandArrow(True)
95 self.mirrorToolButton.setExpandArrow(True)
97 self.scaleForm = openglGui.glFrame(self, (2, -2))
98 openglGui.glGuiLayoutGrid(self.scaleForm)
99 openglGui.glLabel(self.scaleForm, 'Scale X', (0,0))
100 self.scaleXctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,0), lambda value: self.OnScaleEntry(value, 0))
101 openglGui.glLabel(self.scaleForm, 'Scale Y', (0,1))
102 self.scaleYctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,1), lambda value: self.OnScaleEntry(value, 1))
103 openglGui.glLabel(self.scaleForm, 'Scale Z', (0,2))
104 self.scaleZctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,2), lambda value: self.OnScaleEntry(value, 2))
105 openglGui.glLabel(self.scaleForm, 'Size X (mm)', (0,4))
106 self.scaleXmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,4), lambda value: self.OnScaleEntryMM(value, 0))
107 openglGui.glLabel(self.scaleForm, 'Size Y (mm)', (0,5))
108 self.scaleYmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,5), lambda value: self.OnScaleEntryMM(value, 1))
109 openglGui.glLabel(self.scaleForm, 'Size Z (mm)', (0,6))
110 self.scaleZmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,6), lambda value: self.OnScaleEntryMM(value, 2))
111 openglGui.glLabel(self.scaleForm, 'Uniform scale', (0,8))
112 self.scaleUniform = openglGui.glCheckbox(self.scaleForm, True, (1,8), None)
114 self._slicer = sliceEngine.Slicer(self._updateSliceProgress)
115 self._sceneUpdateTimer = wx.Timer(self)
116 self.Bind(wx.EVT_TIMER, lambda e : self._slicer.runSlicer(self._scene), self._sceneUpdateTimer)
117 self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
120 self.updateProfileToControls()
121 wx.EVT_IDLE(self, self.OnIdle)
123 def ShowLoadModel(self, button):
125 dlg=wx.FileDialog(self, 'Open 3D model', os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
126 dlg.SetWildcard(meshLoader.wildcardFilter())
127 if dlg.ShowModal() != wx.ID_OK:
130 filename = dlg.GetPath()
132 if not(os.path.exists(filename)):
134 profile.putPreference('lastFile', filename)
135 self.GetParent().GetParent().GetParent().addToModelMRU(filename)
136 self.loadScene([filename])
138 def ShowPrintWindow(self, button):
140 if machineCom.machineIsConnected():
141 printWindow.printFile(self._slicer.getGCodeFilename())
142 elif len(removableStorage.getPossibleSDcardDrives()) > 0:
143 drives = removableStorage.getPossibleSDcardDrives()
148 filename = os.path.basename(profile.getPreference('lastFile'))
149 filename = filename[0:filename.rfind('.')] + '.gcode'
150 shutil.copy(self._slicer.getGCodeFilename(), drive[1] + filename)
152 defPath = profile.getPreference('lastFile')
153 defPath = defPath[0:defPath.rfind('.')] + '.gcode'
154 dlg=wx.FileDialog(self, 'Save toolpath', defPath, style=wx.FD_SAVE)
155 dlg.SetFilename(defPath)
156 dlg.SetWildcard('Toolpath (*.gcode)|*.gcode;*.g')
157 if dlg.ShowModal() != wx.ID_OK:
160 filename = dlg.GetPath()
163 shutil.copy(self._slicer.getGCodeFilename(), filename)
166 if self._animView is not None or self._animZoom is not None:
169 for obj in self._scene.objects():
170 if obj._loadAnim is not None:
174 def OnToolSelect(self, button):
175 if self.rotateToolButton.getSelected():
176 self.tool = previewTools.toolRotate(self)
177 elif self.scaleToolButton.getSelected():
178 self.tool = previewTools.toolScale(self)
179 elif self.mirrorToolButton.getSelected():
180 self.tool = previewTools.toolNone(self)
182 self.tool = previewTools.toolNone(self)
183 self.resetRotationButton.setHidden(not self.rotateToolButton.getSelected())
184 self.layFlatButton.setHidden(not self.rotateToolButton.getSelected())
185 self.resetScaleButton.setHidden(not self.scaleToolButton.getSelected())
186 self.scaleMaxButton.setHidden(not self.scaleToolButton.getSelected())
187 self.scaleForm.setHidden(not self.scaleToolButton.getSelected())
188 self.mirrorXButton.setHidden(not self.mirrorToolButton.getSelected())
189 self.mirrorYButton.setHidden(not self.mirrorToolButton.getSelected())
190 self.mirrorZButton.setHidden(not self.mirrorToolButton.getSelected())
192 def OnRotateReset(self, button):
193 if self._selectedObj is None:
197 def OnLayFlat(self, button):
198 if self._selectedObj is None:
202 def OnScaleReset(self, button):
203 if self._selectedObj is None:
207 def OnScaleMax(self, button):
208 if self._selectedObj is None:
212 def OnMirror(self, axis):
213 if self._selectedObj is None:
215 self._selectedObj.mirror(axis)
218 def OnScaleEntry(self, value, axis):
219 if self._selectedObj is None:
225 self._selectedObj.setScale(value, axis, self.scaleUniform.getValue())
226 self.updateProfileToControls()
229 def OnScaleEntryMM(self, value, axis):
230 if self._selectedObj is None:
236 self._selectedObj.setSize(value, axis, self.scaleUniform.getValue())
237 self.updateProfileToControls()
240 def sceneUpdated(self):
241 self._sceneUpdateTimer.Start(1, True)
242 self._slicer.abortSlicer()
243 self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
246 def _updateSliceProgress(self, progressValue, ready):
247 self.printButton.setDisabled(not ready)
248 self.printButton.setProgressBar(progressValue)
251 def loadScene(self, fileList):
252 for filename in fileList:
254 objList = meshLoader.loadMeshes(filename)
256 traceback.print_exc()
259 obj._loadAnim = anim(1, 0, 1.5)
261 self._scene.centerAll()
262 self._selectObject(obj)
265 def _deleteObject(self, obj):
266 if obj == self._selectedObj:
267 self._selectedObj = None
268 if obj == self._focusObj:
269 self._focusObj = None
270 self._scene.remove(obj)
271 for m in obj._meshList:
272 if m.vbo is not None:
273 self.glReleaseList.append(m.vbo)
274 if self._isSimpleMode:
275 self._scene.arrangeAll()
278 def _selectObject(self, obj, zoom = True):
279 if obj != self._selectedObj:
280 self._selectedObj = obj
281 self.updateProfileToControls()
283 newViewPos = numpy.array([obj.getPosition()[0], obj.getPosition()[1], obj.getMaximum()[2] / 2])
284 self._animView = anim(self._viewTarget.copy(), newViewPos, 0.5)
285 newZoom = obj.getBoundaryCircle() * 6
286 if newZoom > numpy.max(self._machineSize) * 3:
287 newZoom = numpy.max(self._machineSize) * 3
288 self._animZoom = anim(self._zoom, newZoom, 0.5)
290 def updateProfileToControls(self):
291 oldSimpleMode = self._isSimpleMode
292 self._isSimpleMode = profile.getPreference('startMode') == 'Simple'
293 if self._isSimpleMode and not oldSimpleMode:
294 self._scene.arrangeAll()
296 self._machineSize = numpy.array([profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')])
297 self._objColors[0] = profile.getPreferenceColour('model_colour')
298 self._objColors[1] = profile.getPreferenceColour('model_colour2')
299 self._objColors[2] = profile.getPreferenceColour('model_colour3')
300 self._objColors[3] = profile.getPreferenceColour('model_colour4')
301 self._scene.setMachineSize(self._machineSize)
303 if self._selectedObj is not None:
304 scale = self._selectedObj.getScale()
305 size = self._selectedObj.getSize()
306 self.scaleXctrl.setValue(round(scale[0], 2))
307 self.scaleYctrl.setValue(round(scale[1], 2))
308 self.scaleZctrl.setValue(round(scale[2], 2))
309 self.scaleXmmctrl.setValue(round(size[0], 2))
310 self.scaleYmmctrl.setValue(round(size[1], 2))
311 self.scaleZmmctrl.setValue(round(size[2], 2))
313 def OnKeyChar(self, keyCode):
314 if keyCode == wx.WXK_DELETE or keyCode == wx.WXK_NUMPAD_DELETE:
315 if self._selectedObj is not None:
316 self._deleteObject(self._selectedObj)
319 if keyCode == wx.WXK_F3 and wx.GetKeyState(wx.WXK_SHIFT):
320 shaderEditor(self, self.ShaderUpdate, self._objectLoadShader.getVertexShader(), self._objectLoadShader.getFragmentShader())
322 def ShaderUpdate(self, v, f):
323 s = opengl.GLShader(v, f)
325 self._objectLoadShader.release()
326 self._objectLoadShader = s
327 for obj in self._scene.objects():
328 obj._loadAnim = anim(1, 0, 1.5)
331 def OnMouseDown(self,e):
332 self._mouseX = e.GetX()
333 self._mouseY = e.GetY()
334 self._mouseClick3DPos = self._mouse3Dpos
335 self._mouseClickFocus = self._focusObj
337 self._mouseState = 'doubleClick'
339 self._mouseState = 'dragOrClick'
340 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
341 p0 -= self.getObjectCenterPos() - self._viewTarget
342 p1 -= self.getObjectCenterPos() - self._viewTarget
343 if self.tool.OnDragStart(p0, p1):
344 self._mouseState = 'tool'
345 if self._mouseState == 'dragOrClick':
346 if e.GetButton() == 1:
347 if self._focusObj is not None:
348 self._selectObject(self._focusObj, False)
351 def OnMouseUp(self, e):
352 if e.LeftIsDown() or e.MiddleIsDown() or e.RightIsDown():
354 if self._mouseState == 'dragOrClick':
355 if e.GetButton() == 1:
356 if self._focusObj is not None:
357 self._selectObject(self._focusObj)
359 self._selectedObj = None
361 if e.GetButton() == 3 and self._selectedObj == self._focusObj:
363 #menu.Append(-1, 'Test')
364 #self.PopupMenu(menu)
367 elif self._mouseState == 'dragObject' and self._selectedObj is not None:
368 self._scene.pushFree()
370 elif self._mouseState == 'tool':
371 if self.tempMatrix is not None and self._selectedObj is not None:
372 self._selectedObj.applyMatrix(self.tempMatrix)
373 self.tempMatrix = None
374 self.tool.OnDragEnd()
376 self._mouseState = None
378 def OnMouseMotion(self,e):
379 p0, p1 = self.getMouseRay(e.GetX(), e.GetY())
380 p0 -= self.getObjectCenterPos() - self._viewTarget
381 p1 -= self.getObjectCenterPos() - self._viewTarget
383 if e.Dragging() and self._mouseState is not None:
384 if self._mouseState == 'tool':
385 self.tool.OnDrag(p0, p1)
386 elif not e.LeftIsDown() and e.RightIsDown():
387 self._yaw += e.GetX() - self._mouseX
388 self._pitch -= e.GetY() - self._mouseY
389 if self._pitch > 170:
393 elif (e.LeftIsDown() and e.RightIsDown()) or e.MiddleIsDown():
394 self._zoom += e.GetY() - self._mouseY
397 if self._zoom > numpy.max(self._machineSize) * 3:
398 self._zoom = numpy.max(self._machineSize) * 3
399 elif e.LeftIsDown() and self._selectedObj is not None and self._selectedObj == self._mouseClickFocus and not self._isSimpleMode:
400 self._mouseState = 'dragObject'
401 z = max(0, self._mouseClick3DPos[2])
402 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
403 p2, p3 = self.getMouseRay(e.GetX(), e.GetY())
408 cursorZ0 = p0 - (p1 - p0) * (p0[2] / (p1[2] - p0[2]))
409 cursorZ1 = p2 - (p3 - p2) * (p2[2] / (p3[2] - p2[2]))
410 diff = cursorZ1 - cursorZ0
411 self._selectedObj.setPosition(self._selectedObj.getPosition() + diff[0:2])
412 if not e.Dragging() or self._mouseState != 'tool':
413 self.tool.OnMouseMove(p0, p1)
415 self._mouseX = e.GetX()
416 self._mouseY = e.GetY()
418 def OnMouseWheel(self, e):
419 self._zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0
422 if self._zoom > numpy.max(self._machineSize) * 3:
423 self._zoom = numpy.max(self._machineSize) * 3
426 def getMouseRay(self, x, y):
427 if self._viewport is None:
428 return numpy.array([0,0,0],numpy.float32), numpy.array([0,0,1],numpy.float32)
429 p0 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 0, self._modelMatrix, self._projMatrix, self._viewport)
430 p1 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 1, self._modelMatrix, self._projMatrix, self._viewport)
431 p0 -= self._viewTarget
432 p1 -= self._viewTarget
435 def _init3DView(self):
436 # set viewing projection
437 size = self.GetSize()
438 glViewport(0, 0, size.GetWidth(), size.GetHeight())
441 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
443 glDisable(GL_RESCALE_NORMAL)
444 glDisable(GL_LIGHTING)
446 glEnable(GL_DEPTH_TEST)
447 glDisable(GL_CULL_FACE)
449 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
451 glClearColor(0.8, 0.8, 0.8, 1.0)
455 glMatrixMode(GL_PROJECTION)
457 aspect = float(size.GetWidth()) / float(size.GetHeight())
458 gluPerspective(45.0, aspect, 1.0, numpy.max(self._machineSize) * 4)
460 glMatrixMode(GL_MODELVIEW)
462 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
465 if machineCom.machineIsConnected():
466 self.printButton._imageID = 6
467 self.printButton._tooltip = 'Print'
468 elif len(removableStorage.getPossibleSDcardDrives()) > 0:
469 self.printButton._imageID = 2
470 self.printButton._tooltip = 'Toolpath to SD'
472 self.printButton._imageID = 3
473 self.printButton._tooltip = 'Save toolpath'
475 if self._animView is not None:
476 self._viewTarget = self._animView.getPosition()
477 if self._animView.isDone():
478 self._animView = None
479 if self._animZoom is not None:
480 self._zoom = self._animZoom.getPosition()
481 if self._animZoom.isDone():
482 self._animZoom = None
483 if self._objectShader is None:
484 self._objectShader = opengl.GLShader("""
485 varying float light_amount;
489 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
490 gl_FrontColor = gl_Color;
492 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
496 varying float light_amount;
500 gl_FragColor = vec4(gl_Color.xyz * light_amount, gl_Color[3]);
503 self._objectLoadShader = opengl.GLShader("""
504 uniform float intensity;
506 varying float light_amount;
510 vec4 tmp = gl_Vertex;
511 tmp.x += sin(tmp.z/5.0+intensity*30.0) * scale * intensity;
512 tmp.y += sin(tmp.z/3.0+intensity*40.0) * scale * intensity;
513 gl_Position = gl_ModelViewProjectionMatrix * tmp;
514 gl_FrontColor = gl_Color;
516 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
520 uniform float intensity;
521 varying float light_amount;
525 gl_FragColor = vec4(gl_Color.xyz * light_amount, 1.0-intensity);
529 glTranslate(0,0,-self._zoom)
530 glRotate(-self._pitch, 1,0,0)
531 glRotate(self._yaw, 0,0,1)
532 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
534 self._viewport = glGetIntegerv(GL_VIEWPORT)
535 self._modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX)
536 self._projMatrix = glGetDoublev(GL_PROJECTION_MATRIX)
538 glClearColor(1,1,1,1)
539 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
541 for n in xrange(0, len(self._scene.objects())):
542 obj = self._scene.objects()[n]
543 glColor4ub((n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF)
544 self._renderObject(obj)
546 if self._mouseX > -1:
547 n = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)[0][0]
548 if n < len(self._scene.objects()):
549 self._focusObj = self._scene.objects()[n]
551 self._focusObj = None
552 f = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0]
553 self._mouse3Dpos = opengl.unproject(self._mouseX, self._viewport[1] + self._viewport[3] - self._mouseY, f, self._modelMatrix, self._projMatrix, self._viewport)
554 self._mouse3Dpos -= self._viewTarget
557 glTranslate(0,0,-self._zoom)
558 glRotate(-self._pitch, 1,0,0)
559 glRotate(self._yaw, 0,0,1)
560 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
562 glStencilFunc(GL_ALWAYS, 1, 1)
563 glStencilOp(GL_INCR, GL_INCR, GL_INCR)
564 self._objectShader.bind()
565 for obj in self._scene.objects():
566 if obj._loadAnim is not None:
567 if obj._loadAnim.isDone():
571 col = self._objColors[0]
572 if not self._scene.checkPlatform(obj):
573 col = [0.5,0.5,0.5,0.8]
574 glDisable(GL_STENCIL_TEST)
575 if self._selectedObj == obj:
576 glEnable(GL_STENCIL_TEST)
577 if self._focusObj == obj:
578 col = map(lambda n: n * 1.2, col)
579 elif self._focusObj is not None or self._selectedObj is not None and obj != self._selectedObj:
580 col = map(lambda n: n * 0.8, col)
581 glColor4f(col[0], col[1], col[2], col[3])
582 self._renderObject(obj)
583 self._objectShader.unbind()
585 glDisable(GL_STENCIL_TEST)
587 self._objectLoadShader.bind()
588 glColor4f(0.2, 0.6, 1.0, 1.0)
589 for obj in self._scene.objects():
590 if obj._loadAnim is None:
592 self._objectLoadShader.setUniform('intensity', obj._loadAnim.getPosition())
593 self._objectLoadShader.setUniform('scale', obj.getBoundaryCircle() / 10)
594 self._renderObject(obj)
595 self._objectLoadShader.unbind()
600 #Draw the object box-shadow, so you can see where it will collide with other objects.
601 if self._selectedObj is not None and len(self._scene.objects()) > 1:
602 size = self._selectedObj.getSize()[0:2] / 2 + self._scene.getObjectExtend()
604 glTranslatef(self._selectedObj.getPosition()[0], self._selectedObj.getPosition()[1], 0.0)
606 glEnable(GL_CULL_FACE)
607 glColor4f(0,0,0,0.12)
609 glVertex3f(-size[0], size[1], 0)
610 glVertex3f(-size[0], -size[1], 0)
611 glVertex3f( size[0], -size[1], 0)
612 glVertex3f( size[0], size[1], 0)
614 glDisable(GL_CULL_FACE)
617 #Draw the outline of the selected object, on top of everything else except the GUI.
618 if self._selectedObj is not None and self._selectedObj._loadAnim is None:
619 glDisable(GL_DEPTH_TEST)
620 glEnable(GL_CULL_FACE)
621 glEnable(GL_STENCIL_TEST)
622 glStencilFunc(GL_EQUAL, 0, 255)
624 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
627 self._renderObject(self._selectedObj)
628 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
630 glViewport(0, 0, self.GetSize().GetWidth(), self.GetSize().GetHeight())
631 glDisable(GL_STENCIL_TEST)
632 glDisable(GL_CULL_FACE)
633 glEnable(GL_DEPTH_TEST)
635 if self._selectedObj is not None:
637 pos = self.getObjectCenterPos()
638 glTranslate(pos[0], pos[1], pos[2])
642 def _renderObject(self, obj):
644 glTranslate(obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2)
646 if self.tempMatrix is not None and obj == self._selectedObj:
647 tempMatrix = opengl.convert3x3MatrixTo4x4(self.tempMatrix)
648 glMultMatrixf(tempMatrix)
650 offset = obj.getDrawOffset()
651 glTranslate(-offset[0], -offset[1], -offset[2] - obj.getSize()[2] / 2)
653 tempMatrix = opengl.convert3x3MatrixTo4x4(obj.getMatrix())
654 glMultMatrixf(tempMatrix)
656 for m in obj._meshList:
658 m.vbo = opengl.GLVBO(m.vertexes, m.normal)
662 def _drawMachine(self):
663 glEnable(GL_CULL_FACE)
666 if profile.getPreference('machine_type') == 'ultimaker':
668 self._objectShader.bind()
669 self._renderObject(self._platformMesh)
670 self._objectShader.unbind()
672 size = [profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')]
673 v0 = [ size[0] / 2, size[1] / 2, size[2]]
674 v1 = [ size[0] / 2,-size[1] / 2, size[2]]
675 v2 = [-size[0] / 2, size[1] / 2, size[2]]
676 v3 = [-size[0] / 2,-size[1] / 2, size[2]]
677 v4 = [ size[0] / 2, size[1] / 2, 0]
678 v5 = [ size[0] / 2,-size[1] / 2, 0]
679 v6 = [-size[0] / 2, size[1] / 2, 0]
680 v7 = [-size[0] / 2,-size[1] / 2, 0]
682 vList = [v0,v1,v3,v2, v1,v0,v4,v5, v2,v3,v7,v6, v0,v2,v6,v4, v3,v1,v5,v7]
683 glEnableClientState(GL_VERTEX_ARRAY)
684 glVertexPointer(3, GL_FLOAT, 3*4, vList)
686 glColor4ub(5, 171, 231, 64)
687 glDrawArrays(GL_QUADS, 0, 4)
688 glColor4ub(5, 171, 231, 96)
689 glDrawArrays(GL_QUADS, 4, 8)
690 glColor4ub(5, 171, 231, 128)
691 glDrawArrays(GL_QUADS, 12, 8)
693 sx = self._machineSize[0]
694 sy = self._machineSize[1]
695 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
696 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
701 x1 = max(min(x1, sx/2), -sx/2)
702 y1 = max(min(y1, sy/2), -sy/2)
703 x2 = max(min(x2, sx/2), -sx/2)
704 y2 = max(min(y2, sy/2), -sy/2)
705 if (x & 1) == (y & 1):
706 glColor4ub(5, 171, 231, 127)
708 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
710 glVertex3f(x1, y1, -0.02)
711 glVertex3f(x2, y1, -0.02)
712 glVertex3f(x2, y2, -0.02)
713 glVertex3f(x1, y2, -0.02)
716 glDisableClientState(GL_VERTEX_ARRAY)
718 glDisable(GL_CULL_FACE)
720 def getObjectCenterPos(self):
721 if self._selectedObj is None:
722 return [0.0, 0.0, 0.0]
723 pos = self._selectedObj.getPosition()
724 size = self._selectedObj.getSize()
725 return [pos[0], pos[1], size[2]/2]
727 def getObjectBoundaryCircle(self):
728 if self._selectedObj is None:
730 return self._selectedObj.getBoundaryCircle()
732 def getObjectSize(self):
733 if self._selectedObj is None:
734 return [0.0, 0.0, 0.0]
735 return self._selectedObj.getSize()
737 def getObjectMatrix(self):
738 if self._selectedObj is None:
739 return numpy.matrix([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
740 return self._selectedObj.getMatrix()
742 class shaderEditor(wx.Dialog):
743 def __init__(self, parent, callback, v, f):
744 super(shaderEditor, self).__init__(parent, title="Shader editor", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
745 self._callback = callback
746 s = wx.BoxSizer(wx.VERTICAL)
748 self._vertex = wx.TextCtrl(self, -1, v, style=wx.TE_MULTILINE)
749 self._fragment = wx.TextCtrl(self, -1, f, style=wx.TE_MULTILINE)
750 s.Add(self._vertex, 1, flag=wx.EXPAND)
751 s.Add(self._fragment, 1, flag=wx.EXPAND)
753 self._vertex.Bind(wx.EVT_TEXT, self.OnText, self._vertex)
754 self._fragment.Bind(wx.EVT_TEXT, self.OnText, self._fragment)
756 self.SetPosition(self.GetParent().GetPosition())
757 self.SetSize((self.GetSize().GetWidth(), self.GetParent().GetSize().GetHeight()))
761 self._callback(self._vertex.GetValue(), self._fragment.GetValue())