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 OnDuplicateObject(self, e):
213 if self._selectedObj is None:
215 self._scene.add(self._selectedObj.copy())
216 self._scene.centerAll()
219 def OnMergeObjects(self, e):
220 if self._selectedObj is None or self._focusObj is None or self._selectedObj == self._focusObj:
222 self._scene.merge(self._selectedObj, self._focusObj)
225 def sceneUpdated(self):
226 self._sceneUpdateTimer.Start(1, True)
227 self._slicer.abortSlicer()
228 self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
231 def _updateSliceProgress(self, progressValue, ready):
232 self.printButton.setDisabled(not ready)
233 self.printButton.setProgressBar(progressValue)
236 def loadScene(self, fileList):
237 for filename in fileList:
239 objList = meshLoader.loadMeshes(filename)
241 traceback.print_exc()
244 obj._loadAnim = openglGui.animation(self, 1, 0, 1.5)
246 self._scene.centerAll()
247 self._selectObject(obj)
250 def _deleteObject(self, obj):
251 if obj == self._selectedObj:
252 self._selectedObj = None
253 if obj == self._focusObj:
254 self._focusObj = None
255 self._scene.remove(obj)
256 for m in obj._meshList:
257 if m.vbo is not None and m.vbo.decRef():
258 self.glReleaseList.append(m.vbo)
259 if self._isSimpleMode:
260 self._scene.arrangeAll()
263 def _selectObject(self, obj, zoom = True):
264 if obj != self._selectedObj:
265 self._selectedObj = obj
266 self.updateProfileToControls()
268 newViewPos = numpy.array([obj.getPosition()[0], obj.getPosition()[1], obj.getMaximum()[2] / 2])
269 self._animView = openglGui.animation(self, self._viewTarget.copy(), newViewPos, 0.5)
270 newZoom = obj.getBoundaryCircle() * 6
271 if newZoom > numpy.max(self._machineSize) * 3:
272 newZoom = numpy.max(self._machineSize) * 3
273 self._animZoom = openglGui.animation(self, self._zoom, newZoom, 0.5)
275 def updateProfileToControls(self):
276 oldSimpleMode = self._isSimpleMode
277 self._isSimpleMode = profile.getPreference('startMode') == 'Simple'
278 if self._isSimpleMode and not oldSimpleMode:
279 self._scene.arrangeAll()
281 self._machineSize = numpy.array([profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')])
282 self._objColors[0] = profile.getPreferenceColour('model_colour')
283 self._objColors[1] = profile.getPreferenceColour('model_colour2')
284 self._objColors[2] = profile.getPreferenceColour('model_colour3')
285 self._objColors[3] = profile.getPreferenceColour('model_colour4')
286 self._scene.setMachineSize(self._machineSize)
287 self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
289 if self._selectedObj is not None:
290 scale = self._selectedObj.getScale()
291 size = self._selectedObj.getSize()
292 self.scaleXctrl.setValue(round(scale[0], 2))
293 self.scaleYctrl.setValue(round(scale[1], 2))
294 self.scaleZctrl.setValue(round(scale[2], 2))
295 self.scaleXmmctrl.setValue(round(size[0], 2))
296 self.scaleYmmctrl.setValue(round(size[1], 2))
297 self.scaleZmmctrl.setValue(round(size[2], 2))
299 def OnKeyChar(self, keyCode):
300 if keyCode == wx.WXK_DELETE or keyCode == wx.WXK_NUMPAD_DELETE:
301 if self._selectedObj is not None:
302 self._deleteObject(self._selectedObj)
305 if keyCode == wx.WXK_F3 and wx.GetKeyState(wx.WXK_SHIFT):
306 shaderEditor(self, self.ShaderUpdate, self._objectLoadShader.getVertexShader(), self._objectLoadShader.getFragmentShader())
308 def ShaderUpdate(self, v, f):
309 s = opengl.GLShader(v, f)
311 self._objectLoadShader.release()
312 self._objectLoadShader = s
313 for obj in self._scene.objects():
314 obj._loadAnim = openglGui.animation(self, 1, 0, 1.5)
317 def OnMouseDown(self,e):
318 self._mouseX = e.GetX()
319 self._mouseY = e.GetY()
320 self._mouseClick3DPos = self._mouse3Dpos
321 self._mouseClickFocus = self._focusObj
323 self._mouseState = 'doubleClick'
325 self._mouseState = 'dragOrClick'
326 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
327 p0 -= self.getObjectCenterPos() - self._viewTarget
328 p1 -= self.getObjectCenterPos() - self._viewTarget
329 if self.tool.OnDragStart(p0, p1):
330 self._mouseState = 'tool'
331 if self._mouseState == 'dragOrClick':
332 if e.GetButton() == 1:
333 if self._focusObj is not None:
334 self._selectObject(self._focusObj, False)
337 def OnMouseUp(self, e):
338 if e.LeftIsDown() or e.MiddleIsDown() or e.RightIsDown():
340 if self._mouseState == 'dragOrClick':
341 if e.GetButton() == 1:
342 if self._focusObj is not None:
343 self._selectObject(self._focusObj)
345 self._selectedObj = None
347 if e.GetButton() == 3:
348 if self._selectedObj is not None and self._selectedObj == self._focusObj:
350 self.Bind(wx.EVT_MENU, self.OnDuplicateObject, menu.Append(-1, 'Duplicate'))
353 if self._selectedObj != self._focusObj and self._focusObj is not None:
355 self.Bind(wx.EVT_MENU, self.OnMergeObjects, menu.Append(-1, 'Merge'))
358 elif self._mouseState == 'dragObject' and self._selectedObj is not None:
359 self._scene.pushFree()
361 elif self._mouseState == 'tool':
362 if self.tempMatrix is not None and self._selectedObj is not None:
363 self._selectedObj.applyMatrix(self.tempMatrix)
364 self.tempMatrix = None
365 self.tool.OnDragEnd()
367 self._mouseState = None
369 def OnMouseMotion(self,e):
370 p0, p1 = self.getMouseRay(e.GetX(), e.GetY())
371 p0 -= self.getObjectCenterPos() - self._viewTarget
372 p1 -= self.getObjectCenterPos() - self._viewTarget
374 if e.Dragging() and self._mouseState is not None:
375 if self._mouseState == 'tool':
376 self.tool.OnDrag(p0, p1)
377 elif not e.LeftIsDown() and e.RightIsDown():
378 self._yaw += e.GetX() - self._mouseX
379 self._pitch -= e.GetY() - self._mouseY
380 if self._pitch > 170:
384 elif (e.LeftIsDown() and e.RightIsDown()) or e.MiddleIsDown():
385 self._zoom += e.GetY() - self._mouseY
388 if self._zoom > numpy.max(self._machineSize) * 3:
389 self._zoom = numpy.max(self._machineSize) * 3
390 elif e.LeftIsDown() and self._selectedObj is not None and self._selectedObj == self._mouseClickFocus and not self._isSimpleMode:
391 self._mouseState = 'dragObject'
392 z = max(0, self._mouseClick3DPos[2])
393 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
394 p2, p3 = self.getMouseRay(e.GetX(), e.GetY())
399 cursorZ0 = p0 - (p1 - p0) * (p0[2] / (p1[2] - p0[2]))
400 cursorZ1 = p2 - (p3 - p2) * (p2[2] / (p3[2] - p2[2]))
401 diff = cursorZ1 - cursorZ0
402 self._selectedObj.setPosition(self._selectedObj.getPosition() + diff[0:2])
403 if not e.Dragging() or self._mouseState != 'tool':
404 self.tool.OnMouseMove(p0, p1)
406 self._mouseX = e.GetX()
407 self._mouseY = e.GetY()
409 def OnMouseWheel(self, e):
410 self._zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0
413 if self._zoom > numpy.max(self._machineSize) * 3:
414 self._zoom = numpy.max(self._machineSize) * 3
417 def getMouseRay(self, x, y):
418 if self._viewport is None:
419 return numpy.array([0,0,0],numpy.float32), numpy.array([0,0,1],numpy.float32)
420 p0 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 0, self._modelMatrix, self._projMatrix, self._viewport)
421 p1 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 1, self._modelMatrix, self._projMatrix, self._viewport)
422 p0 -= self._viewTarget
423 p1 -= self._viewTarget
426 def _init3DView(self):
427 # set viewing projection
428 size = self.GetSize()
429 glViewport(0, 0, size.GetWidth(), size.GetHeight())
432 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
434 glDisable(GL_RESCALE_NORMAL)
435 glDisable(GL_LIGHTING)
437 glEnable(GL_DEPTH_TEST)
438 glDisable(GL_CULL_FACE)
440 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
442 glClearColor(0.8, 0.8, 0.8, 1.0)
446 glMatrixMode(GL_PROJECTION)
448 aspect = float(size.GetWidth()) / float(size.GetHeight())
449 gluPerspective(45.0, aspect, 1.0, numpy.max(self._machineSize) * 4)
451 glMatrixMode(GL_MODELVIEW)
453 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
456 if machineCom.machineIsConnected():
457 self.printButton._imageID = 6
458 self.printButton._tooltip = 'Print'
459 elif len(removableStorage.getPossibleSDcardDrives()) > 0:
460 self.printButton._imageID = 2
461 self.printButton._tooltip = 'Toolpath to SD'
463 self.printButton._imageID = 3
464 self.printButton._tooltip = 'Save toolpath'
466 if self._animView is not None:
467 self._viewTarget = self._animView.getPosition()
468 if self._animView.isDone():
469 self._animView = None
470 if self._animZoom is not None:
471 self._zoom = self._animZoom.getPosition()
472 if self._animZoom.isDone():
473 self._animZoom = None
474 if self._objectShader is None:
475 self._objectShader = opengl.GLShader("""
476 varying float light_amount;
480 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
481 gl_FrontColor = gl_Color;
483 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
487 varying float light_amount;
491 gl_FragColor = vec4(gl_Color.xyz * light_amount, gl_Color[3]);
494 self._objectLoadShader = opengl.GLShader("""
495 uniform float intensity;
497 varying float light_amount;
501 vec4 tmp = gl_Vertex;
502 tmp.x += sin(tmp.z/5.0+intensity*30.0) * scale * intensity;
503 tmp.y += sin(tmp.z/3.0+intensity*40.0) * scale * intensity;
504 gl_Position = gl_ModelViewProjectionMatrix * tmp;
505 gl_FrontColor = gl_Color;
507 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
511 uniform float intensity;
512 varying float light_amount;
516 gl_FragColor = vec4(gl_Color.xyz * light_amount, 1.0-intensity);
520 glTranslate(0,0,-self._zoom)
521 glRotate(-self._pitch, 1,0,0)
522 glRotate(self._yaw, 0,0,1)
523 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
525 self._viewport = glGetIntegerv(GL_VIEWPORT)
526 self._modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX)
527 self._projMatrix = glGetDoublev(GL_PROJECTION_MATRIX)
529 glClearColor(1,1,1,1)
530 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
532 for n in xrange(0, len(self._scene.objects())):
533 obj = self._scene.objects()[n]
534 glColor4ub((n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF)
535 self._renderObject(obj)
537 if self._mouseX > -1:
538 n = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)[0][0]
539 if n < len(self._scene.objects()):
540 self._focusObj = self._scene.objects()[n]
542 self._focusObj = None
543 f = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0]
544 self._mouse3Dpos = opengl.unproject(self._mouseX, self._viewport[1] + self._viewport[3] - self._mouseY, f, self._modelMatrix, self._projMatrix, self._viewport)
545 self._mouse3Dpos -= self._viewTarget
548 glTranslate(0,0,-self._zoom)
549 glRotate(-self._pitch, 1,0,0)
550 glRotate(self._yaw, 0,0,1)
551 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
553 glStencilFunc(GL_ALWAYS, 1, 1)
554 glStencilOp(GL_INCR, GL_INCR, GL_INCR)
555 self._objectShader.bind()
556 for obj in self._scene.objects():
557 if obj._loadAnim is not None:
558 if obj._loadAnim.isDone():
563 glDisable(GL_STENCIL_TEST)
564 if self._selectedObj == obj:
565 glEnable(GL_STENCIL_TEST)
566 if self._focusObj == obj:
568 elif self._focusObj is not None or self._selectedObj is not None and obj != self._selectedObj:
570 if not self._scene.checkPlatform(obj):
571 glColor4f(0.5 * brightness, 0.5 * brightness, 0.5 * brightness, 0.8 * brightness)
572 self._renderObject(obj)
574 self._renderObject(obj, brightness)
575 self._objectShader.unbind()
577 glDisable(GL_STENCIL_TEST)
579 self._objectLoadShader.bind()
580 glColor4f(0.2, 0.6, 1.0, 1.0)
581 for obj in self._scene.objects():
582 if obj._loadAnim is None:
584 self._objectLoadShader.setUniform('intensity', obj._loadAnim.getPosition())
585 self._objectLoadShader.setUniform('scale', obj.getBoundaryCircle() / 10)
586 self._renderObject(obj)
587 self._objectLoadShader.unbind()
592 #Draw the object box-shadow, so you can see where it will collide with other objects.
593 if self._selectedObj is not None and len(self._scene.objects()) > 1:
594 size = self._selectedObj.getSize()[0:2] / 2 + self._scene.getObjectExtend()
596 glTranslatef(self._selectedObj.getPosition()[0], self._selectedObj.getPosition()[1], 0.0)
598 glEnable(GL_CULL_FACE)
599 glColor4f(0,0,0,0.12)
601 glVertex3f(-size[0], size[1], 0)
602 glVertex3f(-size[0], -size[1], 0)
603 glVertex3f( size[0], -size[1], 0)
604 glVertex3f( size[0], size[1], 0)
606 glDisable(GL_CULL_FACE)
609 #Draw the outline of the selected object, on top of everything else except the GUI.
610 if self._selectedObj is not None and self._selectedObj._loadAnim is None:
611 glDisable(GL_DEPTH_TEST)
612 glEnable(GL_CULL_FACE)
613 glEnable(GL_STENCIL_TEST)
615 glStencilFunc(GL_EQUAL, 0, 255)
617 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
620 self._renderObject(self._selectedObj)
621 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
623 glViewport(0, 0, self.GetSize().GetWidth(), self.GetSize().GetHeight())
624 glDisable(GL_STENCIL_TEST)
625 glDisable(GL_CULL_FACE)
626 glEnable(GL_DEPTH_TEST)
628 if self._selectedObj is not None:
630 pos = self.getObjectCenterPos()
631 glTranslate(pos[0], pos[1], pos[2])
635 def _renderObject(self, obj, brightness = False):
637 glTranslate(obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2)
639 if self.tempMatrix is not None and obj == self._selectedObj:
640 tempMatrix = opengl.convert3x3MatrixTo4x4(self.tempMatrix)
641 glMultMatrixf(tempMatrix)
643 offset = obj.getDrawOffset()
644 glTranslate(-offset[0], -offset[1], -offset[2] - obj.getSize()[2] / 2)
646 tempMatrix = opengl.convert3x3MatrixTo4x4(obj.getMatrix())
647 glMultMatrixf(tempMatrix)
650 for m in obj._meshList:
652 m.vbo = opengl.GLVBO(m.vertexes, m.normal)
654 glColor4fv(map(lambda n: n * brightness, self._objColors[n]))
659 def _drawMachine(self):
660 glEnable(GL_CULL_FACE)
663 if profile.getPreference('machine_type') == 'ultimaker':
665 self._objectShader.bind()
666 self._renderObject(self._platformMesh)
667 self._objectShader.unbind()
669 size = [profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')]
670 v0 = [ size[0] / 2, size[1] / 2, size[2]]
671 v1 = [ size[0] / 2,-size[1] / 2, size[2]]
672 v2 = [-size[0] / 2, size[1] / 2, size[2]]
673 v3 = [-size[0] / 2,-size[1] / 2, size[2]]
674 v4 = [ size[0] / 2, size[1] / 2, 0]
675 v5 = [ size[0] / 2,-size[1] / 2, 0]
676 v6 = [-size[0] / 2, size[1] / 2, 0]
677 v7 = [-size[0] / 2,-size[1] / 2, 0]
679 vList = [v0,v1,v3,v2, v1,v0,v4,v5, v2,v3,v7,v6, v0,v2,v6,v4, v3,v1,v5,v7]
680 glEnableClientState(GL_VERTEX_ARRAY)
681 glVertexPointer(3, GL_FLOAT, 3*4, vList)
683 glColor4ub(5, 171, 231, 64)
684 glDrawArrays(GL_QUADS, 0, 4)
685 glColor4ub(5, 171, 231, 96)
686 glDrawArrays(GL_QUADS, 4, 8)
687 glColor4ub(5, 171, 231, 128)
688 glDrawArrays(GL_QUADS, 12, 8)
690 sx = self._machineSize[0]
691 sy = self._machineSize[1]
692 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
693 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
698 x1 = max(min(x1, sx/2), -sx/2)
699 y1 = max(min(y1, sy/2), -sy/2)
700 x2 = max(min(x2, sx/2), -sx/2)
701 y2 = max(min(y2, sy/2), -sy/2)
702 if (x & 1) == (y & 1):
703 glColor4ub(5, 171, 231, 127)
705 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
707 glVertex3f(x1, y1, -0.02)
708 glVertex3f(x2, y1, -0.02)
709 glVertex3f(x2, y2, -0.02)
710 glVertex3f(x1, y2, -0.02)
713 glDisableClientState(GL_VERTEX_ARRAY)
715 glDisable(GL_CULL_FACE)
717 def getObjectCenterPos(self):
718 if self._selectedObj is None:
719 return [0.0, 0.0, 0.0]
720 pos = self._selectedObj.getPosition()
721 size = self._selectedObj.getSize()
722 return [pos[0], pos[1], size[2]/2]
724 def getObjectBoundaryCircle(self):
725 if self._selectedObj is None:
727 return self._selectedObj.getBoundaryCircle()
729 def getObjectSize(self):
730 if self._selectedObj is None:
731 return [0.0, 0.0, 0.0]
732 return self._selectedObj.getSize()
734 def getObjectMatrix(self):
735 if self._selectedObj is None:
736 return numpy.matrix([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
737 return self._selectedObj.getMatrix()
739 class shaderEditor(wx.Dialog):
740 def __init__(self, parent, callback, v, f):
741 super(shaderEditor, self).__init__(parent, title="Shader editor", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
742 self._callback = callback
743 s = wx.BoxSizer(wx.VERTICAL)
745 self._vertex = wx.TextCtrl(self, -1, v, style=wx.TE_MULTILINE)
746 self._fragment = wx.TextCtrl(self, -1, f, style=wx.TE_MULTILINE)
747 s.Add(self._vertex, 1, flag=wx.EXPAND)
748 s.Add(self._fragment, 1, flag=wx.EXPAND)
750 self._vertex.Bind(wx.EVT_TEXT, self.OnText, self._vertex)
751 self._fragment.Bind(wx.EVT_TEXT, self.OnText, self._fragment)
753 self.SetPosition(self.GetParent().GetPosition())
754 self.SetSize((self.GetSize().GetWidth(), self.GetParent().GetSize().GetHeight()))
758 self._callback(self._vertex.GetValue(), self._fragment.GetValue())