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.updateToolButtons()
103 self.updateProfileToControls()
105 def ShowLoadModel(self, button):
107 dlg=wx.FileDialog(self, 'Open 3D model', os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
108 dlg.SetWildcard(meshLoader.wildcardFilter())
109 if dlg.ShowModal() != wx.ID_OK:
112 filename = dlg.GetPath()
114 if not(os.path.exists(filename)):
116 profile.putPreference('lastFile', filename)
117 self.GetParent().GetParent().GetParent().addToModelMRU(filename)
118 self.loadScene([filename])
120 def ShowPrintWindow(self, button):
122 if machineCom.machineIsConnected():
123 printWindow.printFile(self._slicer.getGCodeFilename())
124 elif len(removableStorage.getPossibleSDcardDrives()) > 0:
125 drives = removableStorage.getPossibleSDcardDrives()
130 filename = os.path.basename(profile.getPreference('lastFile'))
131 filename = filename[0:filename.rfind('.')] + '.gcode'
132 shutil.copy(self._slicer.getGCodeFilename(), drive[1] + filename)
134 defPath = profile.getPreference('lastFile')
135 defPath = defPath[0:defPath.rfind('.')] + '.gcode'
136 dlg=wx.FileDialog(self, 'Save toolpath', defPath, style=wx.FD_SAVE)
137 dlg.SetFilename(defPath)
138 dlg.SetWildcard('Toolpath (*.gcode)|*.gcode;*.g')
139 if dlg.ShowModal() != wx.ID_OK:
142 filename = dlg.GetPath()
145 shutil.copy(self._slicer.getGCodeFilename(), filename)
147 def OnToolSelect(self, button):
148 if self.rotateToolButton.getSelected():
149 self.tool = previewTools.toolRotate(self)
150 elif self.scaleToolButton.getSelected():
151 self.tool = previewTools.toolScale(self)
152 elif self.mirrorToolButton.getSelected():
153 self.tool = previewTools.toolNone(self)
155 self.tool = previewTools.toolNone(self)
156 self.resetRotationButton.setHidden(not self.rotateToolButton.getSelected())
157 self.layFlatButton.setHidden(not self.rotateToolButton.getSelected())
158 self.resetScaleButton.setHidden(not self.scaleToolButton.getSelected())
159 self.scaleMaxButton.setHidden(not self.scaleToolButton.getSelected())
160 self.scaleForm.setHidden(not self.scaleToolButton.getSelected())
161 self.mirrorXButton.setHidden(not self.mirrorToolButton.getSelected())
162 self.mirrorYButton.setHidden(not self.mirrorToolButton.getSelected())
163 self.mirrorZButton.setHidden(not self.mirrorToolButton.getSelected())
165 def updateToolButtons(self):
166 if self._selectedObj is None:
170 self.rotateToolButton.setHidden(hidden)
171 self.scaleToolButton.setHidden(hidden)
172 self.mirrorToolButton.setHidden(hidden)
174 self.rotateToolButton.setSelected(False)
175 self.scaleToolButton.setSelected(False)
176 self.mirrorToolButton.setSelected(False)
179 def OnRotateReset(self, button):
180 if self._selectedObj is None:
182 self._selectedObj.resetRotation()
184 def OnLayFlat(self, button):
185 if self._selectedObj is None:
187 self._selectedObj.layFlat()
189 def OnScaleReset(self, button):
190 if self._selectedObj is None:
192 self._selectedObj.resetScale()
194 def OnScaleMax(self, button):
195 if self._selectedObj is None:
197 self._selectedObj.scaleUpTo(self._machineSize)
199 def OnMirror(self, axis):
200 if self._selectedObj is None:
202 self._selectedObj.mirror(axis)
205 def OnScaleEntry(self, value, axis):
206 if self._selectedObj is None:
212 self._selectedObj.setScale(value, axis, self.scaleUniform.getValue())
213 self.updateProfileToControls()
216 def OnScaleEntryMM(self, value, axis):
217 if self._selectedObj is None:
223 self._selectedObj.setSize(value, axis, self.scaleUniform.getValue())
224 self.updateProfileToControls()
227 def OnDuplicateObject(self, e):
228 if self._selectedObj is None:
230 self._scene.add(self._selectedObj.copy())
231 self._scene.centerAll()
234 def OnMergeObjects(self, e):
235 if self._selectedObj is None or self._focusObj is None or self._selectedObj == self._focusObj:
237 self._scene.merge(self._selectedObj, self._focusObj)
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 = openglGui.animation(self, 1, 0, 1.5)
261 self._scene.centerAll()
262 self._selectObject(obj)
265 def _deleteObject(self, obj):
266 if obj == self._selectedObj:
267 self._selectObject(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 and m.vbo.decRef():
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()
282 self.updateToolButtons()
283 if zoom and obj is not None:
284 newViewPos = numpy.array([obj.getPosition()[0], obj.getPosition()[1], obj.getMaximum()[2] / 2])
285 self._animView = openglGui.animation(self, self._viewTarget.copy(), newViewPos, 0.5)
286 newZoom = obj.getBoundaryCircle() * 6
287 if newZoom > numpy.max(self._machineSize) * 3:
288 newZoom = numpy.max(self._machineSize) * 3
289 self._animZoom = openglGui.animation(self, self._zoom, newZoom, 0.5)
291 def updateProfileToControls(self):
292 oldSimpleMode = self._isSimpleMode
293 self._isSimpleMode = profile.getPreference('startMode') == 'Simple'
294 if self._isSimpleMode and not oldSimpleMode:
295 self._scene.arrangeAll()
297 self._machineSize = numpy.array([profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')])
298 self._objColors[0] = profile.getPreferenceColour('model_colour')
299 self._objColors[1] = profile.getPreferenceColour('model_colour2')
300 self._objColors[2] = profile.getPreferenceColour('model_colour3')
301 self._objColors[3] = profile.getPreferenceColour('model_colour4')
302 self._scene.setMachineSize(self._machineSize)
303 self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
305 if self._selectedObj is not None:
306 scale = self._selectedObj.getScale()
307 size = self._selectedObj.getSize()
308 self.scaleXctrl.setValue(round(scale[0], 2))
309 self.scaleYctrl.setValue(round(scale[1], 2))
310 self.scaleZctrl.setValue(round(scale[2], 2))
311 self.scaleXmmctrl.setValue(round(size[0], 2))
312 self.scaleYmmctrl.setValue(round(size[1], 2))
313 self.scaleZmmctrl.setValue(round(size[2], 2))
315 def OnKeyChar(self, keyCode):
316 if keyCode == wx.WXK_DELETE or keyCode == wx.WXK_NUMPAD_DELETE:
317 if self._selectedObj is not None:
318 self._deleteObject(self._selectedObj)
321 if keyCode == wx.WXK_F3 and wx.GetKeyState(wx.WXK_SHIFT):
322 shaderEditor(self, self.ShaderUpdate, self._objectLoadShader.getVertexShader(), self._objectLoadShader.getFragmentShader())
324 def ShaderUpdate(self, v, f):
325 s = opengl.GLShader(v, f)
327 self._objectLoadShader.release()
328 self._objectLoadShader = s
329 for obj in self._scene.objects():
330 obj._loadAnim = openglGui.animation(self, 1, 0, 1.5)
333 def OnMouseDown(self,e):
334 self._mouseX = e.GetX()
335 self._mouseY = e.GetY()
336 self._mouseClick3DPos = self._mouse3Dpos
337 self._mouseClickFocus = self._focusObj
339 self._mouseState = 'doubleClick'
341 self._mouseState = 'dragOrClick'
342 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
343 p0 -= self.getObjectCenterPos() - self._viewTarget
344 p1 -= self.getObjectCenterPos() - self._viewTarget
345 if self.tool.OnDragStart(p0, p1):
346 self._mouseState = 'tool'
347 if self._mouseState == 'dragOrClick':
348 if e.GetButton() == 1:
349 if self._focusObj is not None:
350 self._selectObject(self._focusObj, False)
353 def OnMouseUp(self, e):
354 if e.LeftIsDown() or e.MiddleIsDown() or e.RightIsDown():
356 if self._mouseState == 'dragOrClick':
357 if e.GetButton() == 1:
358 self._selectObject(self._focusObj)
359 if e.GetButton() == 3:
360 if self._selectedObj is not None and self._selectedObj == self._focusObj:
362 self.Bind(wx.EVT_MENU, self.OnDuplicateObject, menu.Append(-1, 'Duplicate'))
365 if self._selectedObj != self._focusObj and self._focusObj is not None:
367 self.Bind(wx.EVT_MENU, self.OnMergeObjects, menu.Append(-1, 'Merge'))
370 elif self._mouseState == 'dragObject' and self._selectedObj is not None:
371 self._scene.pushFree()
373 elif self._mouseState == 'tool':
374 if self.tempMatrix is not None and self._selectedObj is not None:
375 self._selectedObj.applyMatrix(self.tempMatrix)
376 self.tempMatrix = None
377 self.tool.OnDragEnd()
379 self._mouseState = None
381 def OnMouseMotion(self,e):
382 p0, p1 = self.getMouseRay(e.GetX(), e.GetY())
383 p0 -= self.getObjectCenterPos() - self._viewTarget
384 p1 -= self.getObjectCenterPos() - self._viewTarget
386 if e.Dragging() and self._mouseState is not None:
387 if self._mouseState == 'tool':
388 self.tool.OnDrag(p0, p1)
389 elif not e.LeftIsDown() and e.RightIsDown():
390 self._yaw += e.GetX() - self._mouseX
391 self._pitch -= e.GetY() - self._mouseY
392 if self._pitch > 170:
396 elif (e.LeftIsDown() and e.RightIsDown()) or e.MiddleIsDown():
397 self._zoom += e.GetY() - self._mouseY
400 if self._zoom > numpy.max(self._machineSize) * 3:
401 self._zoom = numpy.max(self._machineSize) * 3
402 elif e.LeftIsDown() and self._selectedObj is not None and self._selectedObj == self._mouseClickFocus and not self._isSimpleMode:
403 self._mouseState = 'dragObject'
404 z = max(0, self._mouseClick3DPos[2])
405 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
406 p2, p3 = self.getMouseRay(e.GetX(), e.GetY())
411 cursorZ0 = p0 - (p1 - p0) * (p0[2] / (p1[2] - p0[2]))
412 cursorZ1 = p2 - (p3 - p2) * (p2[2] / (p3[2] - p2[2]))
413 diff = cursorZ1 - cursorZ0
414 self._selectedObj.setPosition(self._selectedObj.getPosition() + diff[0:2])
415 if not e.Dragging() or self._mouseState != 'tool':
416 self.tool.OnMouseMove(p0, p1)
418 self._mouseX = e.GetX()
419 self._mouseY = e.GetY()
421 def OnMouseWheel(self, e):
422 self._zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0
425 if self._zoom > numpy.max(self._machineSize) * 3:
426 self._zoom = numpy.max(self._machineSize) * 3
429 def getMouseRay(self, x, y):
430 if self._viewport is None:
431 return numpy.array([0,0,0],numpy.float32), numpy.array([0,0,1],numpy.float32)
432 p0 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 0, self._modelMatrix, self._projMatrix, self._viewport)
433 p1 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 1, self._modelMatrix, self._projMatrix, self._viewport)
434 p0 -= self._viewTarget
435 p1 -= self._viewTarget
438 def _init3DView(self):
439 # set viewing projection
440 size = self.GetSize()
441 glViewport(0, 0, size.GetWidth(), size.GetHeight())
444 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
446 glDisable(GL_RESCALE_NORMAL)
447 glDisable(GL_LIGHTING)
449 glEnable(GL_DEPTH_TEST)
450 glDisable(GL_CULL_FACE)
452 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
454 glClearColor(0.8, 0.8, 0.8, 1.0)
458 glMatrixMode(GL_PROJECTION)
460 aspect = float(size.GetWidth()) / float(size.GetHeight())
461 gluPerspective(45.0, aspect, 1.0, numpy.max(self._machineSize) * 4)
463 glMatrixMode(GL_MODELVIEW)
465 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
468 if machineCom.machineIsConnected():
469 self.printButton._imageID = 6
470 self.printButton._tooltip = 'Print'
471 elif len(removableStorage.getPossibleSDcardDrives()) > 0:
472 self.printButton._imageID = 2
473 self.printButton._tooltip = 'Toolpath to SD'
475 self.printButton._imageID = 3
476 self.printButton._tooltip = 'Save toolpath'
478 if self._animView is not None:
479 self._viewTarget = self._animView.getPosition()
480 if self._animView.isDone():
481 self._animView = None
482 if self._animZoom is not None:
483 self._zoom = self._animZoom.getPosition()
484 if self._animZoom.isDone():
485 self._animZoom = None
486 if self._objectShader is None:
487 self._objectShader = opengl.GLShader("""
488 varying float light_amount;
492 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
493 gl_FrontColor = gl_Color;
495 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
499 varying float light_amount;
503 gl_FragColor = vec4(gl_Color.xyz * light_amount, gl_Color[3]);
506 self._objectLoadShader = opengl.GLShader("""
507 uniform float intensity;
509 varying float light_amount;
513 vec4 tmp = gl_Vertex;
514 tmp.x += sin(tmp.z/5.0+intensity*30.0) * scale * intensity;
515 tmp.y += sin(tmp.z/3.0+intensity*40.0) * scale * intensity;
516 gl_Position = gl_ModelViewProjectionMatrix * tmp;
517 gl_FrontColor = gl_Color;
519 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
523 uniform float intensity;
524 varying float light_amount;
528 gl_FragColor = vec4(gl_Color.xyz * light_amount, 1.0-intensity);
532 glTranslate(0,0,-self._zoom)
533 glRotate(-self._pitch, 1,0,0)
534 glRotate(self._yaw, 0,0,1)
535 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
537 self._viewport = glGetIntegerv(GL_VIEWPORT)
538 self._modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX)
539 self._projMatrix = glGetDoublev(GL_PROJECTION_MATRIX)
541 glClearColor(1,1,1,1)
542 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
544 for n in xrange(0, len(self._scene.objects())):
545 obj = self._scene.objects()[n]
546 glColor4ub((n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF)
547 self._renderObject(obj)
549 if self._mouseX > -1:
550 n = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)[0][0]
551 if n < len(self._scene.objects()):
552 self._focusObj = self._scene.objects()[n]
554 self._focusObj = None
555 f = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0]
556 self._mouse3Dpos = opengl.unproject(self._mouseX, self._viewport[1] + self._viewport[3] - self._mouseY, f, self._modelMatrix, self._projMatrix, self._viewport)
557 self._mouse3Dpos -= self._viewTarget
560 glTranslate(0,0,-self._zoom)
561 glRotate(-self._pitch, 1,0,0)
562 glRotate(self._yaw, 0,0,1)
563 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
565 glStencilFunc(GL_ALWAYS, 1, 1)
566 glStencilOp(GL_INCR, GL_INCR, GL_INCR)
567 self._objectShader.bind()
568 for obj in self._scene.objects():
569 if obj._loadAnim is not None:
570 if obj._loadAnim.isDone():
575 glDisable(GL_STENCIL_TEST)
576 if self._selectedObj == obj:
577 glEnable(GL_STENCIL_TEST)
578 if self._focusObj == obj:
580 elif self._focusObj is not None or self._selectedObj is not None and obj != self._selectedObj:
582 if not self._scene.checkPlatform(obj):
583 glColor4f(0.5 * brightness, 0.5 * brightness, 0.5 * brightness, 0.8 * brightness)
584 self._renderObject(obj)
586 self._renderObject(obj, brightness)
587 self._objectShader.unbind()
589 glDisable(GL_STENCIL_TEST)
591 self._objectLoadShader.bind()
592 glColor4f(0.2, 0.6, 1.0, 1.0)
593 for obj in self._scene.objects():
594 if obj._loadAnim is None:
596 self._objectLoadShader.setUniform('intensity', obj._loadAnim.getPosition())
597 self._objectLoadShader.setUniform('scale', obj.getBoundaryCircle() / 10)
598 self._renderObject(obj)
599 self._objectLoadShader.unbind()
604 #Draw the object box-shadow, so you can see where it will collide with other objects.
605 if self._selectedObj is not None and len(self._scene.objects()) > 1:
606 size = self._selectedObj.getSize()[0:2] / 2 + self._scene.getObjectExtend()
608 glTranslatef(self._selectedObj.getPosition()[0], self._selectedObj.getPosition()[1], 0.0)
610 glEnable(GL_CULL_FACE)
611 glColor4f(0,0,0,0.12)
613 glVertex3f(-size[0], size[1], 0)
614 glVertex3f(-size[0], -size[1], 0)
615 glVertex3f( size[0], -size[1], 0)
616 glVertex3f( size[0], size[1], 0)
618 glDisable(GL_CULL_FACE)
621 #Draw the outline of the selected object, on top of everything else except the GUI.
622 if self._selectedObj is not None and self._selectedObj._loadAnim is None:
623 glDisable(GL_DEPTH_TEST)
624 glEnable(GL_CULL_FACE)
625 glEnable(GL_STENCIL_TEST)
627 glStencilFunc(GL_EQUAL, 0, 255)
629 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
632 self._renderObject(self._selectedObj)
633 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
635 glViewport(0, 0, self.GetSize().GetWidth(), self.GetSize().GetHeight())
636 glDisable(GL_STENCIL_TEST)
637 glDisable(GL_CULL_FACE)
638 glEnable(GL_DEPTH_TEST)
640 if self._selectedObj is not None:
642 pos = self.getObjectCenterPos()
643 glTranslate(pos[0], pos[1], pos[2])
647 def _renderObject(self, obj, brightness = False):
649 glTranslate(obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2)
651 if self.tempMatrix is not None and obj == self._selectedObj:
652 tempMatrix = opengl.convert3x3MatrixTo4x4(self.tempMatrix)
653 glMultMatrixf(tempMatrix)
655 offset = obj.getDrawOffset()
656 glTranslate(-offset[0], -offset[1], -offset[2] - obj.getSize()[2] / 2)
658 tempMatrix = opengl.convert3x3MatrixTo4x4(obj.getMatrix())
659 glMultMatrixf(tempMatrix)
662 for m in obj._meshList:
664 m.vbo = opengl.GLVBO(m.vertexes, m.normal)
666 glColor4fv(map(lambda n: n * brightness, self._objColors[n]))
671 def _drawMachine(self):
672 glEnable(GL_CULL_FACE)
675 if profile.getPreference('machine_type') == 'ultimaker':
677 self._objectShader.bind()
678 self._renderObject(self._platformMesh)
679 self._objectShader.unbind()
681 size = [profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')]
682 v0 = [ size[0] / 2, size[1] / 2, size[2]]
683 v1 = [ size[0] / 2,-size[1] / 2, size[2]]
684 v2 = [-size[0] / 2, size[1] / 2, size[2]]
685 v3 = [-size[0] / 2,-size[1] / 2, size[2]]
686 v4 = [ size[0] / 2, size[1] / 2, 0]
687 v5 = [ size[0] / 2,-size[1] / 2, 0]
688 v6 = [-size[0] / 2, size[1] / 2, 0]
689 v7 = [-size[0] / 2,-size[1] / 2, 0]
691 vList = [v0,v1,v3,v2, v1,v0,v4,v5, v2,v3,v7,v6, v0,v2,v6,v4, v3,v1,v5,v7]
692 glEnableClientState(GL_VERTEX_ARRAY)
693 glVertexPointer(3, GL_FLOAT, 3*4, vList)
695 glColor4ub(5, 171, 231, 64)
696 glDrawArrays(GL_QUADS, 0, 4)
697 glColor4ub(5, 171, 231, 96)
698 glDrawArrays(GL_QUADS, 4, 8)
699 glColor4ub(5, 171, 231, 128)
700 glDrawArrays(GL_QUADS, 12, 8)
702 sx = self._machineSize[0]
703 sy = self._machineSize[1]
704 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
705 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
710 x1 = max(min(x1, sx/2), -sx/2)
711 y1 = max(min(y1, sy/2), -sy/2)
712 x2 = max(min(x2, sx/2), -sx/2)
713 y2 = max(min(y2, sy/2), -sy/2)
714 if (x & 1) == (y & 1):
715 glColor4ub(5, 171, 231, 127)
717 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
719 glVertex3f(x1, y1, -0.02)
720 glVertex3f(x2, y1, -0.02)
721 glVertex3f(x2, y2, -0.02)
722 glVertex3f(x1, y2, -0.02)
725 glDisableClientState(GL_VERTEX_ARRAY)
727 glDisable(GL_CULL_FACE)
729 def getObjectCenterPos(self):
730 if self._selectedObj is None:
731 return [0.0, 0.0, 0.0]
732 pos = self._selectedObj.getPosition()
733 size = self._selectedObj.getSize()
734 return [pos[0], pos[1], size[2]/2]
736 def getObjectBoundaryCircle(self):
737 if self._selectedObj is None:
739 return self._selectedObj.getBoundaryCircle()
741 def getObjectSize(self):
742 if self._selectedObj is None:
743 return [0.0, 0.0, 0.0]
744 return self._selectedObj.getSize()
746 def getObjectMatrix(self):
747 if self._selectedObj is None:
748 return numpy.matrix([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
749 return self._selectedObj.getMatrix()
751 class shaderEditor(wx.Dialog):
752 def __init__(self, parent, callback, v, f):
753 super(shaderEditor, self).__init__(parent, title="Shader editor", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
754 self._callback = callback
755 s = wx.BoxSizer(wx.VERTICAL)
757 self._vertex = wx.TextCtrl(self, -1, v, style=wx.TE_MULTILINE)
758 self._fragment = wx.TextCtrl(self, -1, f, style=wx.TE_MULTILINE)
759 s.Add(self._vertex, 1, flag=wx.EXPAND)
760 s.Add(self._fragment, 1, flag=wx.EXPAND)
762 self._vertex.Bind(wx.EVT_TEXT, self.OnText, self._vertex)
763 self._fragment.Bind(wx.EVT_TEXT, self.OnText, self._fragment)
765 self.SetPosition(self.GetParent().GetPosition())
766 self.SetSize((self.GetSize().GetWidth(), self.GetParent().GetSize().GetHeight()))
770 self._callback(self._vertex.GetValue(), self._fragment.GetValue())