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
27 class SceneView(openglGui.glGuiPanel):
28 def __init__(self, parent):
29 super(SceneView, self).__init__(parent)
34 self._scene = objectScene.Scene()
35 self._objectShader = None
37 self._selectedObj = None
38 self._objColors = [None,None,None,None]
41 self._mouseState = None
42 self._viewTarget = numpy.array([0,0,0], numpy.float32)
45 self._platformMesh = meshLoader.loadMeshes(resources.getPathForMesh('ultimaker_platform.stl'))[0]
46 self._platformMesh._drawOffset = numpy.array([0,0,1.5], numpy.float32)
47 self._isSimpleMode = True
50 self._modelMatrix = None
51 self._projMatrix = None
52 self.tempMatrix = None
54 self.openFileButton = openglGui.glButton(self, 4, 'Load', (0,0), self.ShowLoadModel)
55 self.printButton = openglGui.glButton(self, 6, 'Print', (1,0), self.ShowPrintWindow)
56 self.printButton.setDisabled(True)
59 self.rotateToolButton = openglGui.glRadioButton(self, 8, 'Rotate', (0,-1), group, self.OnToolSelect)
60 self.scaleToolButton = openglGui.glRadioButton(self, 9, 'Scale', (1,-1), group, self.OnToolSelect)
61 self.mirrorToolButton = openglGui.glRadioButton(self, 10, 'Mirror', (2,-1), group, self.OnToolSelect)
63 self.resetRotationButton = openglGui.glButton(self, 12, 'Reset', (0,-2), self.OnRotateReset)
64 self.layFlatButton = openglGui.glButton(self, 16, 'Lay flat', (0,-3), self.OnLayFlat)
66 self.resetScaleButton = openglGui.glButton(self, 13, 'Reset', (1,-2), self.OnScaleReset)
67 self.scaleMaxButton = openglGui.glButton(self, 17, 'To max', (1,-3), self.OnScaleMax)
69 self.mirrorXButton = openglGui.glButton(self, 14, 'Mirror X', (2,-2), lambda button: self.OnMirror(0))
70 self.mirrorYButton = openglGui.glButton(self, 18, 'Mirror Y', (2,-3), lambda button: self.OnMirror(1))
71 self.mirrorZButton = openglGui.glButton(self, 22, 'Mirror Z', (2,-4), lambda button: self.OnMirror(2))
73 self.rotateToolButton.setExpandArrow(True)
74 self.scaleToolButton.setExpandArrow(True)
75 self.mirrorToolButton.setExpandArrow(True)
77 self.scaleForm = openglGui.glFrame(self, (2, -2))
78 openglGui.glGuiLayoutGrid(self.scaleForm)
79 openglGui.glLabel(self.scaleForm, 'Scale X', (0,0))
80 self.scaleXctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,0), lambda value: self.OnScaleEntry(value, 0))
81 openglGui.glLabel(self.scaleForm, 'Scale Y', (0,1))
82 self.scaleYctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,1), lambda value: self.OnScaleEntry(value, 1))
83 openglGui.glLabel(self.scaleForm, 'Scale Z', (0,2))
84 self.scaleZctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,2), lambda value: self.OnScaleEntry(value, 2))
85 openglGui.glLabel(self.scaleForm, 'Size X (mm)', (0,4))
86 self.scaleXmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,4), lambda value: self.OnScaleEntryMM(value, 0))
87 openglGui.glLabel(self.scaleForm, 'Size Y (mm)', (0,5))
88 self.scaleYmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,5), lambda value: self.OnScaleEntryMM(value, 1))
89 openglGui.glLabel(self.scaleForm, 'Size Z (mm)', (0,6))
90 self.scaleZmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,6), lambda value: self.OnScaleEntryMM(value, 2))
91 openglGui.glLabel(self.scaleForm, 'Uniform scale', (0,8))
92 self.scaleUniform = openglGui.glCheckbox(self.scaleForm, True, (1,8), None)
94 self.notification = openglGui.glNotification(self, (0, 0))
96 self._slicer = sliceEngine.Slicer(self._updateSliceProgress)
97 self._sceneUpdateTimer = wx.Timer(self)
98 self.Bind(wx.EVT_TIMER, lambda e : self._slicer.runSlicer(self._scene), self._sceneUpdateTimer)
99 self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
102 self.updateProfileToControls()
104 def ShowLoadModel(self, button):
106 dlg=wx.FileDialog(self, 'Open 3D model', os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
107 dlg.SetWildcard(meshLoader.wildcardFilter())
108 if dlg.ShowModal() != wx.ID_OK:
111 filename = dlg.GetPath()
113 if not(os.path.exists(filename)):
115 profile.putPreference('lastFile', filename)
116 self.GetParent().GetParent().GetParent().addToModelMRU(filename)
117 self.loadScene([filename])
119 def ShowPrintWindow(self, button):
121 if machineCom.machineIsConnected():
122 printWindow.printFile(self._slicer.getGCodeFilename())
123 elif len(removableStorage.getPossibleSDcardDrives()) > 0:
124 drives = removableStorage.getPossibleSDcardDrives()
129 filename = os.path.basename(profile.getPreference('lastFile'))
130 filename = filename[0:filename.rfind('.')] + '.gcode'
131 shutil.copy(self._slicer.getGCodeFilename(), drive[1] + filename)
133 defPath = profile.getPreference('lastFile')
134 defPath = defPath[0:defPath.rfind('.')] + '.gcode'
135 dlg=wx.FileDialog(self, 'Save toolpath', defPath, style=wx.FD_SAVE)
136 dlg.SetFilename(defPath)
137 dlg.SetWildcard('Toolpath (*.gcode)|*.gcode;*.g')
138 if dlg.ShowModal() != wx.ID_OK:
141 filename = dlg.GetPath()
144 shutil.copy(self._slicer.getGCodeFilename(), filename)
146 def OnToolSelect(self, button):
147 if self.rotateToolButton.getSelected():
148 self.tool = previewTools.toolRotate(self)
149 elif self.scaleToolButton.getSelected():
150 self.tool = previewTools.toolScale(self)
151 elif self.mirrorToolButton.getSelected():
152 self.tool = previewTools.toolNone(self)
154 self.tool = previewTools.toolNone(self)
155 self.resetRotationButton.setHidden(not self.rotateToolButton.getSelected())
156 self.layFlatButton.setHidden(not self.rotateToolButton.getSelected())
157 self.resetScaleButton.setHidden(not self.scaleToolButton.getSelected())
158 self.scaleMaxButton.setHidden(not self.scaleToolButton.getSelected())
159 self.scaleForm.setHidden(not self.scaleToolButton.getSelected())
160 self.mirrorXButton.setHidden(not self.mirrorToolButton.getSelected())
161 self.mirrorYButton.setHidden(not self.mirrorToolButton.getSelected())
162 self.mirrorZButton.setHidden(not self.mirrorToolButton.getSelected())
164 def OnRotateReset(self, button):
165 if self._selectedObj is None:
167 self._selectedObj.resetRotation()
169 def OnLayFlat(self, button):
170 if self._selectedObj is None:
172 self._selectedObj.layFlat()
174 def OnScaleReset(self, button):
175 if self._selectedObj is None:
177 self._selectedObj.resetScale()
179 def OnScaleMax(self, button):
180 if self._selectedObj is None:
182 self._selectedObj.scaleUpTo(self._machineSize)
184 def OnMirror(self, axis):
185 if self._selectedObj is None:
187 self._selectedObj.mirror(axis)
190 def OnScaleEntry(self, value, axis):
191 if self._selectedObj is None:
197 self._selectedObj.setScale(value, axis, self.scaleUniform.getValue())
198 self.updateProfileToControls()
201 def OnScaleEntryMM(self, value, axis):
202 if self._selectedObj is None:
208 self._selectedObj.setSize(value, axis, self.scaleUniform.getValue())
209 self.updateProfileToControls()
212 def OnMergeObjects(self, e):
213 if self._selectedObj is None or self._focusObj is None or self._selectedObj == self._focusObj:
215 self._scene.merge(self._selectedObj, self._focusObj)
218 def sceneUpdated(self):
219 self._sceneUpdateTimer.Start(1, True)
220 self._slicer.abortSlicer()
221 self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
224 def _updateSliceProgress(self, progressValue, ready):
225 self.printButton.setDisabled(not ready)
226 self.printButton.setProgressBar(progressValue)
229 def loadScene(self, fileList):
230 for filename in fileList:
232 objList = meshLoader.loadMeshes(filename)
234 traceback.print_exc()
237 obj._loadAnim = openglGui.animation(self, 1, 0, 1.5)
239 self._scene.centerAll()
240 self._selectObject(obj)
243 def _deleteObject(self, obj):
244 if obj == self._selectedObj:
245 self._selectedObj = None
246 if obj == self._focusObj:
247 self._focusObj = None
248 self._scene.remove(obj)
249 for m in obj._meshList:
250 if m.vbo is not None:
251 self.glReleaseList.append(m.vbo)
252 if self._isSimpleMode:
253 self._scene.arrangeAll()
256 def _selectObject(self, obj, zoom = True):
257 if obj != self._selectedObj:
258 self._selectedObj = obj
259 self.updateProfileToControls()
261 newViewPos = numpy.array([obj.getPosition()[0], obj.getPosition()[1], obj.getMaximum()[2] / 2])
262 self._animView = openglGui.animation(self, self._viewTarget.copy(), newViewPos, 0.5)
263 newZoom = obj.getBoundaryCircle() * 6
264 if newZoom > numpy.max(self._machineSize) * 3:
265 newZoom = numpy.max(self._machineSize) * 3
266 self._animZoom = openglGui.animation(self, self._zoom, newZoom, 0.5)
268 def updateProfileToControls(self):
269 oldSimpleMode = self._isSimpleMode
270 self._isSimpleMode = profile.getPreference('startMode') == 'Simple'
271 if self._isSimpleMode and not oldSimpleMode:
272 self._scene.arrangeAll()
274 self._machineSize = numpy.array([profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')])
275 self._objColors[0] = profile.getPreferenceColour('model_colour')
276 self._objColors[1] = profile.getPreferenceColour('model_colour2')
277 self._objColors[2] = profile.getPreferenceColour('model_colour3')
278 self._objColors[3] = profile.getPreferenceColour('model_colour4')
279 self._scene.setMachineSize(self._machineSize)
280 self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
282 if self._selectedObj is not None:
283 scale = self._selectedObj.getScale()
284 size = self._selectedObj.getSize()
285 self.scaleXctrl.setValue(round(scale[0], 2))
286 self.scaleYctrl.setValue(round(scale[1], 2))
287 self.scaleZctrl.setValue(round(scale[2], 2))
288 self.scaleXmmctrl.setValue(round(size[0], 2))
289 self.scaleYmmctrl.setValue(round(size[1], 2))
290 self.scaleZmmctrl.setValue(round(size[2], 2))
292 def OnKeyChar(self, keyCode):
293 if keyCode == wx.WXK_DELETE or keyCode == wx.WXK_NUMPAD_DELETE:
294 if self._selectedObj is not None:
295 self._deleteObject(self._selectedObj)
298 if keyCode == wx.WXK_F3 and wx.GetKeyState(wx.WXK_SHIFT):
299 shaderEditor(self, self.ShaderUpdate, self._objectLoadShader.getVertexShader(), self._objectLoadShader.getFragmentShader())
301 def ShaderUpdate(self, v, f):
302 s = opengl.GLShader(v, f)
304 self._objectLoadShader.release()
305 self._objectLoadShader = s
306 for obj in self._scene.objects():
307 obj._loadAnim = openglGui.animation(self, 1, 0, 1.5)
310 def OnMouseDown(self,e):
311 self._mouseX = e.GetX()
312 self._mouseY = e.GetY()
313 self._mouseClick3DPos = self._mouse3Dpos
314 self._mouseClickFocus = self._focusObj
316 self._mouseState = 'doubleClick'
318 self._mouseState = 'dragOrClick'
319 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
320 p0 -= self.getObjectCenterPos() - self._viewTarget
321 p1 -= self.getObjectCenterPos() - self._viewTarget
322 if self.tool.OnDragStart(p0, p1):
323 self._mouseState = 'tool'
324 if self._mouseState == 'dragOrClick':
325 if e.GetButton() == 1:
326 if self._focusObj is not None:
327 self._selectObject(self._focusObj, False)
330 def OnMouseUp(self, e):
331 if e.LeftIsDown() or e.MiddleIsDown() or e.RightIsDown():
333 if self._mouseState == 'dragOrClick':
334 if e.GetButton() == 1:
335 if self._focusObj is not None:
336 self._selectObject(self._focusObj)
338 self._selectedObj = None
340 if e.GetButton() == 3:
341 if self._selectedObj == self._focusObj:
343 #menu.Append(-1, 'Test')
344 #self.PopupMenu(menu)
347 if self._selectedObj != self._focusObj and self._focusObj is not None:
349 self.Bind(wx.EVT_MENU, self.OnMergeObjects, menu.Append(-1, 'Merge'))
352 elif self._mouseState == 'dragObject' and self._selectedObj is not None:
353 self._scene.pushFree()
355 elif self._mouseState == 'tool':
356 if self.tempMatrix is not None and self._selectedObj is not None:
357 self._selectedObj.applyMatrix(self.tempMatrix)
358 self.tempMatrix = None
359 self.tool.OnDragEnd()
361 self._mouseState = None
363 def OnMouseMotion(self,e):
364 p0, p1 = self.getMouseRay(e.GetX(), e.GetY())
365 p0 -= self.getObjectCenterPos() - self._viewTarget
366 p1 -= self.getObjectCenterPos() - self._viewTarget
368 if e.Dragging() and self._mouseState is not None:
369 if self._mouseState == 'tool':
370 self.tool.OnDrag(p0, p1)
371 elif not e.LeftIsDown() and e.RightIsDown():
372 self._yaw += e.GetX() - self._mouseX
373 self._pitch -= e.GetY() - self._mouseY
374 if self._pitch > 170:
378 elif (e.LeftIsDown() and e.RightIsDown()) or e.MiddleIsDown():
379 self._zoom += e.GetY() - self._mouseY
382 if self._zoom > numpy.max(self._machineSize) * 3:
383 self._zoom = numpy.max(self._machineSize) * 3
384 elif e.LeftIsDown() and self._selectedObj is not None and self._selectedObj == self._mouseClickFocus and not self._isSimpleMode:
385 self._mouseState = 'dragObject'
386 z = max(0, self._mouseClick3DPos[2])
387 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
388 p2, p3 = self.getMouseRay(e.GetX(), e.GetY())
393 cursorZ0 = p0 - (p1 - p0) * (p0[2] / (p1[2] - p0[2]))
394 cursorZ1 = p2 - (p3 - p2) * (p2[2] / (p3[2] - p2[2]))
395 diff = cursorZ1 - cursorZ0
396 self._selectedObj.setPosition(self._selectedObj.getPosition() + diff[0:2])
397 if not e.Dragging() or self._mouseState != 'tool':
398 self.tool.OnMouseMove(p0, p1)
400 self._mouseX = e.GetX()
401 self._mouseY = e.GetY()
403 def OnMouseWheel(self, e):
404 self._zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0
407 if self._zoom > numpy.max(self._machineSize) * 3:
408 self._zoom = numpy.max(self._machineSize) * 3
411 def getMouseRay(self, x, y):
412 if self._viewport is None:
413 return numpy.array([0,0,0],numpy.float32), numpy.array([0,0,1],numpy.float32)
414 p0 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 0, self._modelMatrix, self._projMatrix, self._viewport)
415 p1 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 1, self._modelMatrix, self._projMatrix, self._viewport)
416 p0 -= self._viewTarget
417 p1 -= self._viewTarget
420 def _init3DView(self):
421 # set viewing projection
422 size = self.GetSize()
423 glViewport(0, 0, size.GetWidth(), size.GetHeight())
426 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
428 glDisable(GL_RESCALE_NORMAL)
429 glDisable(GL_LIGHTING)
431 glEnable(GL_DEPTH_TEST)
432 glDisable(GL_CULL_FACE)
434 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
436 glClearColor(0.8, 0.8, 0.8, 1.0)
440 glMatrixMode(GL_PROJECTION)
442 aspect = float(size.GetWidth()) / float(size.GetHeight())
443 gluPerspective(45.0, aspect, 1.0, numpy.max(self._machineSize) * 4)
445 glMatrixMode(GL_MODELVIEW)
447 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
450 if machineCom.machineIsConnected():
451 self.printButton._imageID = 6
452 self.printButton._tooltip = 'Print'
453 elif len(removableStorage.getPossibleSDcardDrives()) > 0:
454 self.printButton._imageID = 2
455 self.printButton._tooltip = 'Toolpath to SD'
457 self.printButton._imageID = 3
458 self.printButton._tooltip = 'Save toolpath'
460 if self._animView is not None:
461 self._viewTarget = self._animView.getPosition()
462 if self._animView.isDone():
463 self._animView = None
464 if self._animZoom is not None:
465 self._zoom = self._animZoom.getPosition()
466 if self._animZoom.isDone():
467 self._animZoom = None
468 if self._objectShader is None:
469 self._objectShader = opengl.GLShader("""
470 varying float light_amount;
474 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
475 gl_FrontColor = gl_Color;
477 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
481 varying float light_amount;
485 gl_FragColor = vec4(gl_Color.xyz * light_amount, gl_Color[3]);
488 self._objectLoadShader = opengl.GLShader("""
489 uniform float intensity;
491 varying float light_amount;
495 vec4 tmp = gl_Vertex;
496 tmp.x += sin(tmp.z/5.0+intensity*30.0) * scale * intensity;
497 tmp.y += sin(tmp.z/3.0+intensity*40.0) * scale * intensity;
498 gl_Position = gl_ModelViewProjectionMatrix * tmp;
499 gl_FrontColor = gl_Color;
501 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
505 uniform float intensity;
506 varying float light_amount;
510 gl_FragColor = vec4(gl_Color.xyz * light_amount, 1.0-intensity);
514 glTranslate(0,0,-self._zoom)
515 glRotate(-self._pitch, 1,0,0)
516 glRotate(self._yaw, 0,0,1)
517 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
519 self._viewport = glGetIntegerv(GL_VIEWPORT)
520 self._modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX)
521 self._projMatrix = glGetDoublev(GL_PROJECTION_MATRIX)
523 glClearColor(1,1,1,1)
524 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
526 for n in xrange(0, len(self._scene.objects())):
527 obj = self._scene.objects()[n]
528 glColor4ub((n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF)
529 self._renderObject(obj)
531 if self._mouseX > -1:
532 n = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)[0][0]
533 if n < len(self._scene.objects()):
534 self._focusObj = self._scene.objects()[n]
536 self._focusObj = None
537 f = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0]
538 self._mouse3Dpos = opengl.unproject(self._mouseX, self._viewport[1] + self._viewport[3] - self._mouseY, f, self._modelMatrix, self._projMatrix, self._viewport)
539 self._mouse3Dpos -= self._viewTarget
542 glTranslate(0,0,-self._zoom)
543 glRotate(-self._pitch, 1,0,0)
544 glRotate(self._yaw, 0,0,1)
545 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
547 glStencilFunc(GL_ALWAYS, 1, 1)
548 glStencilOp(GL_INCR, GL_INCR, GL_INCR)
549 self._objectShader.bind()
550 for obj in self._scene.objects():
551 if obj._loadAnim is not None:
552 if obj._loadAnim.isDone():
557 glDisable(GL_STENCIL_TEST)
558 if self._selectedObj == obj:
559 glEnable(GL_STENCIL_TEST)
560 if self._focusObj == obj:
562 elif self._focusObj is not None or self._selectedObj is not None and obj != self._selectedObj:
564 if not self._scene.checkPlatform(obj):
565 glColor4f(0.5 * brightness, 0.5 * brightness, 0.5 * brightness, 0.8 * brightness)
566 self._renderObject(obj)
568 self._renderObject(obj, brightness)
569 self._objectShader.unbind()
571 glDisable(GL_STENCIL_TEST)
573 self._objectLoadShader.bind()
574 glColor4f(0.2, 0.6, 1.0, 1.0)
575 for obj in self._scene.objects():
576 if obj._loadAnim is None:
578 self._objectLoadShader.setUniform('intensity', obj._loadAnim.getPosition())
579 self._objectLoadShader.setUniform('scale', obj.getBoundaryCircle() / 10)
580 self._renderObject(obj)
581 self._objectLoadShader.unbind()
586 #Draw the object box-shadow, so you can see where it will collide with other objects.
587 if self._selectedObj is not None and len(self._scene.objects()) > 1:
588 size = self._selectedObj.getSize()[0:2] / 2 + self._scene.getObjectExtend()
590 glTranslatef(self._selectedObj.getPosition()[0], self._selectedObj.getPosition()[1], 0.0)
592 glEnable(GL_CULL_FACE)
593 glColor4f(0,0,0,0.12)
595 glVertex3f(-size[0], size[1], 0)
596 glVertex3f(-size[0], -size[1], 0)
597 glVertex3f( size[0], -size[1], 0)
598 glVertex3f( size[0], size[1], 0)
600 glDisable(GL_CULL_FACE)
603 #Draw the outline of the selected object, on top of everything else except the GUI.
604 if self._selectedObj is not None and self._selectedObj._loadAnim is None:
605 glDisable(GL_DEPTH_TEST)
606 glEnable(GL_CULL_FACE)
607 glEnable(GL_STENCIL_TEST)
609 glStencilFunc(GL_EQUAL, 0, 255)
611 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
614 self._renderObject(self._selectedObj)
615 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
617 glViewport(0, 0, self.GetSize().GetWidth(), self.GetSize().GetHeight())
618 glDisable(GL_STENCIL_TEST)
619 glDisable(GL_CULL_FACE)
620 glEnable(GL_DEPTH_TEST)
622 if self._selectedObj is not None:
624 pos = self.getObjectCenterPos()
625 glTranslate(pos[0], pos[1], pos[2])
629 def _renderObject(self, obj, brightness = False):
631 glTranslate(obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2)
633 if self.tempMatrix is not None and obj == self._selectedObj:
634 tempMatrix = opengl.convert3x3MatrixTo4x4(self.tempMatrix)
635 glMultMatrixf(tempMatrix)
637 offset = obj.getDrawOffset()
638 glTranslate(-offset[0], -offset[1], -offset[2] - obj.getSize()[2] / 2)
640 tempMatrix = opengl.convert3x3MatrixTo4x4(obj.getMatrix())
641 glMultMatrixf(tempMatrix)
644 for m in obj._meshList:
646 m.vbo = opengl.GLVBO(m.vertexes, m.normal)
648 glColor4fv(map(lambda n: n * brightness, self._objColors[n]))
653 def _drawMachine(self):
654 glEnable(GL_CULL_FACE)
657 if profile.getPreference('machine_type') == 'ultimaker':
659 self._objectShader.bind()
660 self._renderObject(self._platformMesh)
661 self._objectShader.unbind()
663 size = [profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')]
664 v0 = [ size[0] / 2, size[1] / 2, size[2]]
665 v1 = [ size[0] / 2,-size[1] / 2, size[2]]
666 v2 = [-size[0] / 2, size[1] / 2, size[2]]
667 v3 = [-size[0] / 2,-size[1] / 2, size[2]]
668 v4 = [ size[0] / 2, size[1] / 2, 0]
669 v5 = [ size[0] / 2,-size[1] / 2, 0]
670 v6 = [-size[0] / 2, size[1] / 2, 0]
671 v7 = [-size[0] / 2,-size[1] / 2, 0]
673 vList = [v0,v1,v3,v2, v1,v0,v4,v5, v2,v3,v7,v6, v0,v2,v6,v4, v3,v1,v5,v7]
674 glEnableClientState(GL_VERTEX_ARRAY)
675 glVertexPointer(3, GL_FLOAT, 3*4, vList)
677 glColor4ub(5, 171, 231, 64)
678 glDrawArrays(GL_QUADS, 0, 4)
679 glColor4ub(5, 171, 231, 96)
680 glDrawArrays(GL_QUADS, 4, 8)
681 glColor4ub(5, 171, 231, 128)
682 glDrawArrays(GL_QUADS, 12, 8)
684 sx = self._machineSize[0]
685 sy = self._machineSize[1]
686 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
687 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
692 x1 = max(min(x1, sx/2), -sx/2)
693 y1 = max(min(y1, sy/2), -sy/2)
694 x2 = max(min(x2, sx/2), -sx/2)
695 y2 = max(min(y2, sy/2), -sy/2)
696 if (x & 1) == (y & 1):
697 glColor4ub(5, 171, 231, 127)
699 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
701 glVertex3f(x1, y1, -0.02)
702 glVertex3f(x2, y1, -0.02)
703 glVertex3f(x2, y2, -0.02)
704 glVertex3f(x1, y2, -0.02)
707 glDisableClientState(GL_VERTEX_ARRAY)
709 glDisable(GL_CULL_FACE)
711 def getObjectCenterPos(self):
712 if self._selectedObj is None:
713 return [0.0, 0.0, 0.0]
714 pos = self._selectedObj.getPosition()
715 size = self._selectedObj.getSize()
716 return [pos[0], pos[1], size[2]/2]
718 def getObjectBoundaryCircle(self):
719 if self._selectedObj is None:
721 return self._selectedObj.getBoundaryCircle()
723 def getObjectSize(self):
724 if self._selectedObj is None:
725 return [0.0, 0.0, 0.0]
726 return self._selectedObj.getSize()
728 def getObjectMatrix(self):
729 if self._selectedObj is None:
730 return numpy.matrix([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
731 return self._selectedObj.getMatrix()
733 class shaderEditor(wx.Dialog):
734 def __init__(self, parent, callback, v, f):
735 super(shaderEditor, self).__init__(parent, title="Shader editor", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
736 self._callback = callback
737 s = wx.BoxSizer(wx.VERTICAL)
739 self._vertex = wx.TextCtrl(self, -1, v, style=wx.TE_MULTILINE)
740 self._fragment = wx.TextCtrl(self, -1, f, style=wx.TE_MULTILINE)
741 s.Add(self._vertex, 1, flag=wx.EXPAND)
742 s.Add(self._fragment, 1, flag=wx.EXPAND)
744 self._vertex.Bind(wx.EVT_TEXT, self.OnText, self._vertex)
745 self._fragment.Bind(wx.EVT_TEXT, self.OnText, self._fragment)
747 self.SetPosition(self.GetParent().GetPosition())
748 self.SetSize((self.GetSize().GetWidth(), self.GetParent().GetSize().GetHeight()))
752 self._callback(self._vertex.GetValue(), self._fragment.GetValue())