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,0.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)
217 def sceneUpdated(self):
218 self._sceneUpdateTimer.Start(1, True)
219 self._slicer.abortSlicer()
220 self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
223 def _updateSliceProgress(self, progressValue, ready):
224 self.printButton.setDisabled(not ready)
225 self.printButton.setProgressBar(progressValue)
228 def loadScene(self, fileList):
229 for filename in fileList:
231 objList = meshLoader.loadMeshes(filename)
233 traceback.print_exc()
236 obj._loadAnim = anim(1, 0, 1.5)
238 self._scene.centerAll()
239 self._selectObject(obj)
242 def _deleteObject(self, obj):
243 if obj == self._selectedObj:
244 self._selectedObj = None
245 if obj == self._focusObj:
246 self._focusObj = None
247 self._scene.remove(obj)
248 for m in obj._meshList:
249 if m.vbo is not None:
250 self.glReleaseList.append(m.vbo)
251 if self._isSimpleMode:
252 self._scene.arrangeAll()
255 def _selectObject(self, obj, zoom = True):
256 if obj != self._selectedObj:
257 self._selectedObj = obj
259 newViewPos = numpy.array([obj.getPosition()[0], obj.getPosition()[1], obj.getMaximum()[2] / 2])
260 self._animView = anim(self._viewTarget.copy(), newViewPos, 0.5)
261 newZoom = obj.getBoundaryCircle() * 6
262 if newZoom > numpy.max(self._machineSize) * 3:
263 newZoom = numpy.max(self._machineSize) * 3
264 self._animZoom = anim(self._zoom, newZoom, 0.5)
266 def updateProfileToControls(self):
267 oldSimpleMode = self._isSimpleMode
268 self._isSimpleMode = profile.getPreference('startMode') == 'Simple'
269 if self._isSimpleMode and not oldSimpleMode:
270 self._scene.arrangeAll()
272 self._machineSize = numpy.array([profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')])
273 self._objColors[0] = profile.getPreferenceColour('model_colour')
274 self._objColors[1] = profile.getPreferenceColour('model_colour2')
275 self._objColors[2] = profile.getPreferenceColour('model_colour3')
276 self._objColors[3] = profile.getPreferenceColour('model_colour4')
277 self._scene.setMachineSize(self._machineSize)
279 def OnKeyChar(self, keyCode):
280 if keyCode == wx.WXK_DELETE or keyCode == wx.WXK_NUMPAD_DELETE:
281 if self._selectedObj is not None:
282 self._deleteObject(self._selectedObj)
285 if keyCode == wx.WXK_F3 and wx.GetKeyState(wx.WXK_SHIFT):
286 shaderEditor(self, self.ShaderUpdate, self._objectLoadShader.getVertexShader(), self._objectLoadShader.getFragmentShader())
288 def ShaderUpdate(self, v, f):
289 s = opengl.GLShader(v, f)
291 self._objectLoadShader.release()
292 self._objectLoadShader = s
293 for obj in self._scene.objects():
294 obj._loadAnim = anim(1, 0, 1.5)
297 def OnMouseDown(self,e):
298 self._mouseX = e.GetX()
299 self._mouseY = e.GetY()
300 self._mouseClick3DPos = self._mouse3Dpos
301 self._mouseClickFocus = self._focusObj
303 self._mouseState = 'doubleClick'
305 self._mouseState = 'dragOrClick'
306 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
307 p0 -= self.getObjectCenterPos() - self._viewTarget
308 p1 -= self.getObjectCenterPos() - self._viewTarget
309 if self.tool.OnDragStart(p0, p1):
310 self._mouseState = 'tool'
311 if self._mouseState == 'dragOrClick':
312 if e.GetButton() == 1:
313 if self._focusObj is not None:
314 self._selectObject(self._focusObj, False)
317 def OnMouseUp(self, e):
318 if e.LeftIsDown() or e.MiddleIsDown() or e.RightIsDown():
320 if self._mouseState == 'dragOrClick':
321 if e.GetButton() == 1:
322 if self._focusObj is not None:
323 self._selectObject(self._focusObj)
325 self._selectedObj = None
327 if e.GetButton() == 3 and self._selectedObj == self._focusObj:
329 #menu.Append(-1, 'Test')
330 #self.PopupMenu(menu)
333 elif self._mouseState == 'dragObject' and self._selectedObj is not None:
334 self._scene.pushFree()
336 elif self._mouseState == 'tool':
337 if self.tempMatrix is not None and self._selectedObj is not None:
338 self._selectedObj.applyMatrix(self.tempMatrix)
339 self.tempMatrix = None
340 self.tool.OnDragEnd()
342 self._mouseState = None
344 def OnMouseMotion(self,e):
345 p0, p1 = self.getMouseRay(e.GetX(), e.GetY())
346 p0 -= self.getObjectCenterPos() - self._viewTarget
347 p1 -= self.getObjectCenterPos() - self._viewTarget
349 if e.Dragging() and self._mouseState is not None:
350 if self._mouseState == 'tool':
351 self.tool.OnDrag(p0, p1)
352 elif not e.LeftIsDown() and e.RightIsDown():
353 self._yaw += e.GetX() - self._mouseX
354 self._pitch -= e.GetY() - self._mouseY
355 if self._pitch > 170:
359 elif (e.LeftIsDown() and e.RightIsDown()) or e.MiddleIsDown():
360 self._zoom += e.GetY() - self._mouseY
363 if self._zoom > numpy.max(self._machineSize) * 3:
364 self._zoom = numpy.max(self._machineSize) * 3
365 elif e.LeftIsDown() and self._selectedObj is not None and self._selectedObj == self._mouseClickFocus and not self._isSimpleMode:
366 self._mouseState = 'dragObject'
367 z = max(0, self._mouseClick3DPos[2])
368 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
369 p2, p3 = self.getMouseRay(e.GetX(), e.GetY())
374 cursorZ0 = p0 - (p1 - p0) * (p0[2] / (p1[2] - p0[2]))
375 cursorZ1 = p2 - (p3 - p2) * (p2[2] / (p3[2] - p2[2]))
376 diff = cursorZ1 - cursorZ0
377 self._selectedObj.setPosition(self._selectedObj.getPosition() + diff[0:2])
378 if not e.Dragging() or self._mouseState != 'tool':
379 self.tool.OnMouseMove(p0, p1)
381 self._mouseX = e.GetX()
382 self._mouseY = e.GetY()
384 def OnMouseWheel(self, e):
385 self._zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0
388 if self._zoom > numpy.max(self._machineSize) * 3:
389 self._zoom = numpy.max(self._machineSize) * 3
392 def getMouseRay(self, x, y):
393 if self._viewport is None:
394 return numpy.array([0,0,0],numpy.float32), numpy.array([0,0,1],numpy.float32)
395 p0 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 0, self._modelMatrix, self._projMatrix, self._viewport)
396 p1 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 1, self._modelMatrix, self._projMatrix, self._viewport)
397 p0 -= self._viewTarget
398 p1 -= self._viewTarget
401 def _init3DView(self):
402 # set viewing projection
403 size = self.GetSize()
404 glViewport(0, 0, size.GetWidth(), size.GetHeight())
407 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
409 glDisable(GL_RESCALE_NORMAL)
410 glDisable(GL_LIGHTING)
412 glEnable(GL_DEPTH_TEST)
413 glDisable(GL_CULL_FACE)
415 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
417 glClearColor(0.8, 0.8, 0.8, 1.0)
421 glMatrixMode(GL_PROJECTION)
423 aspect = float(size.GetWidth()) / float(size.GetHeight())
424 gluPerspective(45.0, aspect, 1.0, numpy.max(self._machineSize) * 4)
426 glMatrixMode(GL_MODELVIEW)
428 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
431 if machineCom.machineIsConnected():
432 self.printButton._imageID = 6
433 self.printButton._tooltip = 'Print'
434 elif len(removableStorage.getPossibleSDcardDrives()) > 0:
435 self.printButton._imageID = 2
436 self.printButton._tooltip = 'Toolpath to SD'
438 self.printButton._imageID = 3
439 self.printButton._tooltip = 'Save toolpath'
441 if self._animView is not None:
442 self._viewTarget = self._animView.getPosition()
443 if self._animView.isDone():
444 self._animView = None
445 if self._animZoom is not None:
446 self._zoom = self._animZoom.getPosition()
447 if self._animZoom.isDone():
448 self._animZoom = None
449 if self._objectShader is None:
450 self._objectShader = opengl.GLShader("""
451 uniform float cameraDistance;
452 varying float light_amount;
456 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
457 gl_FrontColor = gl_Color;
459 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
460 light_amount *= 1.0 - (length(gl_Position.xyz - vec3(0.0,0.0,cameraDistance)) / 1.5 / cameraDistance);
464 uniform float cameraDistance;
465 varying float light_amount;
469 gl_FragColor = vec4(gl_Color.xyz * light_amount, gl_Color[3]);
472 self._objectLoadShader = opengl.GLShader("""
473 uniform float cameraDistance;
474 uniform float intensity;
476 varying float light_amount;
480 vec4 tmp = gl_Vertex;
481 tmp.x += sin(tmp.z/5.0+intensity*30.0) * scale * intensity;
482 tmp.y += sin(tmp.z/3.0+intensity*40.0) * scale * intensity;
483 gl_Position = gl_ModelViewProjectionMatrix * tmp;
484 gl_FrontColor = gl_Color;
486 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
487 light_amount *= 1.0 - (length(gl_Position.xyz - vec3(0.0,0.0,cameraDistance)) / 1.5 / cameraDistance);
491 uniform float cameraDistance;
492 uniform float intensity;
493 varying float light_amount;
497 gl_FragColor = vec4(gl_Color.xyz * light_amount, 1.0-intensity);
501 glTranslate(0,0,-self._zoom)
502 glRotate(-self._pitch, 1,0,0)
503 glRotate(self._yaw, 0,0,1)
504 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
506 self._viewport = glGetIntegerv(GL_VIEWPORT)
507 self._modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX)
508 self._projMatrix = glGetDoublev(GL_PROJECTION_MATRIX)
510 glClearColor(1,1,1,1)
511 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
513 for n in xrange(0, len(self._scene.objects())):
514 obj = self._scene.objects()[n]
515 glColor4ub((n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF)
516 self._renderObject(obj)
518 if self._mouseX > -1:
519 n = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)[0][0]
520 if n < len(self._scene.objects()):
521 self._focusObj = self._scene.objects()[n]
523 self._focusObj = None
524 f = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0]
525 self._mouse3Dpos = opengl.unproject(self._mouseX, self._viewport[1] + self._viewport[3] - self._mouseY, f, self._modelMatrix, self._projMatrix, self._viewport)
526 self._mouse3Dpos -= self._viewTarget
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 glStencilFunc(GL_ALWAYS, 1, 1)
535 glStencilOp(GL_INCR, GL_INCR, GL_INCR)
536 self._objectShader.bind()
537 self._objectShader.setUniform('cameraDistance', self._zoom)
538 for obj in self._scene.objects():
539 if obj._loadAnim is not None:
540 if obj._loadAnim.isDone():
544 col = self._objColors[0]
545 if not self._scene.checkPlatform(obj):
546 col = [0.5,0.5,0.5,0.8]
547 glDisable(GL_STENCIL_TEST)
548 if self._selectedObj == obj:
549 glEnable(GL_STENCIL_TEST)
550 if self._focusObj == obj:
551 col = map(lambda n: n * 1.2, col)
552 elif self._focusObj is not None or self._selectedObj is not None and obj != self._selectedObj:
553 col = map(lambda n: n * 0.8, col)
554 glColor4f(col[0], col[1], col[2], col[3])
555 self._renderObject(obj)
556 self._objectShader.unbind()
558 glDisable(GL_STENCIL_TEST)
560 self._objectLoadShader.bind()
561 self._objectLoadShader.setUniform('cameraDistance', self._zoom)
562 glColor4f(0.2, 0.6, 1.0, 1.0)
563 for obj in self._scene.objects():
564 if obj._loadAnim is None:
566 self._objectLoadShader.setUniform('intensity', obj._loadAnim.getPosition())
567 self._objectLoadShader.setUniform('scale', obj.getBoundaryCircle() / 10)
568 self._renderObject(obj)
569 self._objectLoadShader.unbind()
574 #Draw the outline of the selected object, on top of everything else except the GUI.
575 if self._selectedObj is not None and self._selectedObj._loadAnim is None:
576 glDisable(GL_DEPTH_TEST)
577 glEnable(GL_CULL_FACE)
578 glEnable(GL_STENCIL_TEST)
579 glStencilFunc(GL_EQUAL, 0, 255)
580 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
583 self._renderObject(self._selectedObj)
584 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
585 glDisable(GL_STENCIL_TEST)
586 glDisable(GL_CULL_FACE)
587 glEnable(GL_DEPTH_TEST)
589 if self._selectedObj is not None:
591 pos = self.getObjectCenterPos()
592 glTranslate(pos[0], pos[1], pos[2])
596 def _renderObject(self, obj):
598 glTranslate(obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2)
600 if self.tempMatrix is not None and obj == self._selectedObj:
601 tempMatrix = opengl.convert3x3MatrixTo4x4(self.tempMatrix)
602 glMultMatrixf(tempMatrix)
604 offset = obj.getDrawOffset()
605 glTranslate(-offset[0], -offset[1], -offset[2] - obj.getSize()[2] / 2)
607 tempMatrix = opengl.convert3x3MatrixTo4x4(obj.getMatrix())
608 glMultMatrixf(tempMatrix)
610 for m in obj._meshList:
612 m.vbo = opengl.GLVBO(m.vertexes, m.normal)
616 def _drawMachine(self):
617 glEnable(GL_CULL_FACE)
620 if profile.getPreference('machine_type') == 'ultimaker':
622 self._objectShader.bind()
623 self._objectShader.setUniform('cameraDistance', self._zoom)
624 self._renderObject(self._platformMesh)
625 self._objectShader.unbind()
627 size = [profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')]
628 v0 = [ size[0] / 2, size[1] / 2, size[2]]
629 v1 = [ size[0] / 2,-size[1] / 2, size[2]]
630 v2 = [-size[0] / 2, size[1] / 2, size[2]]
631 v3 = [-size[0] / 2,-size[1] / 2, size[2]]
632 v4 = [ size[0] / 2, size[1] / 2, 0]
633 v5 = [ size[0] / 2,-size[1] / 2, 0]
634 v6 = [-size[0] / 2, size[1] / 2, 0]
635 v7 = [-size[0] / 2,-size[1] / 2, 0]
637 vList = [v0,v1,v3,v2, v1,v0,v4,v5, v2,v3,v7,v6, v0,v2,v6,v4, v3,v1,v5,v7]
638 glEnableClientState(GL_VERTEX_ARRAY)
639 glVertexPointer(3, GL_FLOAT, 3*4, vList)
641 glColor4ub(5, 171, 231, 64)
642 glDrawArrays(GL_QUADS, 0, 4)
643 glColor4ub(5, 171, 231, 96)
644 glDrawArrays(GL_QUADS, 4, 8)
645 glColor4ub(5, 171, 231, 128)
646 glDrawArrays(GL_QUADS, 12, 8)
648 sx = self._machineSize[0]
649 sy = self._machineSize[1]
650 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
651 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
656 x1 = max(min(x1, sx/2), -sx/2)
657 y1 = max(min(y1, sy/2), -sy/2)
658 x2 = max(min(x2, sx/2), -sx/2)
659 y2 = max(min(y2, sy/2), -sy/2)
660 if (x & 1) == (y & 1):
661 glColor4ub(5, 171, 231, 127)
663 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
665 glVertex3f(x1, y1, -0.02)
666 glVertex3f(x2, y1, -0.02)
667 glVertex3f(x2, y2, -0.02)
668 glVertex3f(x1, y2, -0.02)
671 glDisableClientState(GL_VERTEX_ARRAY)
673 glDisable(GL_CULL_FACE)
675 def getObjectCenterPos(self):
676 if self._selectedObj is None:
677 return [0.0, 0.0, 0.0]
678 pos = self._selectedObj.getPosition()
679 size = self._selectedObj.getSize()
680 return [pos[0], pos[1], size[2]/2]
682 def getObjectBoundaryCircle(self):
683 if self._selectedObj is None:
685 return self._selectedObj.getBoundaryCircle()
687 def getObjectSize(self):
688 if self._selectedObj is None:
689 return [0.0, 0.0, 0.0]
690 return self._selectedObj.getSize()
692 def getObjectMatrix(self):
693 if self._selectedObj is None:
694 return numpy.matrix([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
695 return self._selectedObj.getMatrix()
697 class shaderEditor(wx.Dialog):
698 def __init__(self, parent, callback, v, f):
699 super(shaderEditor, self).__init__(parent, title="Shader editor", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
700 self._callback = callback
701 s = wx.BoxSizer(wx.VERTICAL)
703 self._vertex = wx.TextCtrl(self, -1, v, style=wx.TE_MULTILINE)
704 self._fragment = wx.TextCtrl(self, -1, f, style=wx.TE_MULTILINE)
705 s.Add(self._vertex, 1, flag=wx.EXPAND)
706 s.Add(self._fragment, 1, flag=wx.EXPAND)
708 self._vertex.Bind(wx.EVT_TEXT, self.OnText, self._vertex)
709 self._fragment.Bind(wx.EVT_TEXT, self.OnText, self._fragment)
711 self.SetPosition(self.GetParent().GetPosition())
712 self.SetSize((self.GetSize().GetWidth(), self.GetParent().GetSize().GetHeight()))
716 self._callback(self._vertex.GetValue(), self._fragment.GetValue())