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 - numpy.array(profile.calculateObjectSizeOffsets() + [0.0], numpy.float32) * 2)
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:
362 self.Bind(wx.EVT_MENU, lambda e: self._deleteObject(self._selectedObj), menu.Append(-1, 'Delete'))
363 if self._selectedObj == self._focusObj:
364 self.Bind(wx.EVT_MENU, self.OnDuplicateObject, menu.Append(-1, 'Duplicate'))
365 if self._selectedObj != self._focusObj and self._focusObj is not None:
366 self.Bind(wx.EVT_MENU, self.OnMergeObjects, menu.Append(-1, 'Merge'))
367 if menu.MenuItemCount > 0:
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._mouseState = 'drag'
391 self._yaw += e.GetX() - self._mouseX
392 self._pitch -= e.GetY() - self._mouseY
393 if self._pitch > 170:
397 elif (e.LeftIsDown() and e.RightIsDown()) or e.MiddleIsDown():
398 self._mouseState = 'drag'
399 self._zoom += e.GetY() - self._mouseY
402 if self._zoom > numpy.max(self._machineSize) * 3:
403 self._zoom = numpy.max(self._machineSize) * 3
404 elif e.LeftIsDown() and self._selectedObj is not None and self._selectedObj == self._mouseClickFocus and not self._isSimpleMode:
405 self._mouseState = 'dragObject'
406 z = max(0, self._mouseClick3DPos[2])
407 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
408 p2, p3 = self.getMouseRay(e.GetX(), e.GetY())
413 cursorZ0 = p0 - (p1 - p0) * (p0[2] / (p1[2] - p0[2]))
414 cursorZ1 = p2 - (p3 - p2) * (p2[2] / (p3[2] - p2[2]))
415 diff = cursorZ1 - cursorZ0
416 self._selectedObj.setPosition(self._selectedObj.getPosition() + diff[0:2])
417 if not e.Dragging() or self._mouseState != 'tool':
418 self.tool.OnMouseMove(p0, p1)
420 self._mouseX = e.GetX()
421 self._mouseY = e.GetY()
423 def OnMouseWheel(self, e):
424 self._zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0
427 if self._zoom > numpy.max(self._machineSize) * 3:
428 self._zoom = numpy.max(self._machineSize) * 3
431 def getMouseRay(self, x, y):
432 if self._viewport is None:
433 return numpy.array([0,0,0],numpy.float32), numpy.array([0,0,1],numpy.float32)
434 p0 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 0, self._modelMatrix, self._projMatrix, self._viewport)
435 p1 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 1, self._modelMatrix, self._projMatrix, self._viewport)
436 p0 -= self._viewTarget
437 p1 -= self._viewTarget
440 def _init3DView(self):
441 # set viewing projection
442 size = self.GetSize()
443 glViewport(0, 0, size.GetWidth(), size.GetHeight())
446 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
448 glDisable(GL_RESCALE_NORMAL)
449 glDisable(GL_LIGHTING)
451 glEnable(GL_DEPTH_TEST)
452 glDisable(GL_CULL_FACE)
454 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
456 glClearColor(0.8, 0.8, 0.8, 1.0)
460 glMatrixMode(GL_PROJECTION)
462 aspect = float(size.GetWidth()) / float(size.GetHeight())
463 gluPerspective(45.0, aspect, 1.0, numpy.max(self._machineSize) * 4)
465 glMatrixMode(GL_MODELVIEW)
467 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
470 if machineCom.machineIsConnected():
471 self.printButton._imageID = 6
472 self.printButton._tooltip = 'Print'
473 elif len(removableStorage.getPossibleSDcardDrives()) > 0:
474 self.printButton._imageID = 2
475 self.printButton._tooltip = 'Toolpath to SD'
477 self.printButton._imageID = 3
478 self.printButton._tooltip = 'Save toolpath'
480 if self._animView is not None:
481 self._viewTarget = self._animView.getPosition()
482 if self._animView.isDone():
483 self._animView = None
484 if self._animZoom is not None:
485 self._zoom = self._animZoom.getPosition()
486 if self._animZoom.isDone():
487 self._animZoom = None
488 if self._objectShader is None:
489 self._objectShader = opengl.GLShader("""
490 varying float light_amount;
494 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
495 gl_FrontColor = gl_Color;
497 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
501 varying float light_amount;
505 gl_FragColor = vec4(gl_Color.xyz * light_amount, gl_Color[3]);
508 self._objectLoadShader = opengl.GLShader("""
509 uniform float intensity;
511 varying float light_amount;
515 vec4 tmp = gl_Vertex;
516 tmp.x += sin(tmp.z/5.0+intensity*30.0) * scale * intensity;
517 tmp.y += sin(tmp.z/3.0+intensity*40.0) * scale * intensity;
518 gl_Position = gl_ModelViewProjectionMatrix * tmp;
519 gl_FrontColor = gl_Color;
521 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
525 uniform float intensity;
526 varying float light_amount;
530 gl_FragColor = vec4(gl_Color.xyz * light_amount, 1.0-intensity);
534 glTranslate(0,0,-self._zoom)
535 glRotate(-self._pitch, 1,0,0)
536 glRotate(self._yaw, 0,0,1)
537 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
539 self._viewport = glGetIntegerv(GL_VIEWPORT)
540 self._modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX)
541 self._projMatrix = glGetDoublev(GL_PROJECTION_MATRIX)
543 glClearColor(1,1,1,1)
544 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
546 for n in xrange(0, len(self._scene.objects())):
547 obj = self._scene.objects()[n]
548 glColor4ub((n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF)
549 self._renderObject(obj)
551 if self._mouseX > -1:
552 n = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)[0][0]
553 if n < len(self._scene.objects()):
554 self._focusObj = self._scene.objects()[n]
556 self._focusObj = None
557 f = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0]
558 self._mouse3Dpos = opengl.unproject(self._mouseX, self._viewport[1] + self._viewport[3] - self._mouseY, f, self._modelMatrix, self._projMatrix, self._viewport)
559 self._mouse3Dpos -= self._viewTarget
562 glTranslate(0,0,-self._zoom)
563 glRotate(-self._pitch, 1,0,0)
564 glRotate(self._yaw, 0,0,1)
565 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
567 glStencilFunc(GL_ALWAYS, 1, 1)
568 glStencilOp(GL_INCR, GL_INCR, GL_INCR)
569 self._objectShader.bind()
570 for obj in self._scene.objects():
571 if obj._loadAnim is not None:
572 if obj._loadAnim.isDone():
577 glDisable(GL_STENCIL_TEST)
578 if self._selectedObj == obj:
579 glEnable(GL_STENCIL_TEST)
580 if self._focusObj == obj:
582 elif self._focusObj is not None or self._selectedObj is not None and obj != self._selectedObj:
584 if not self._scene.checkPlatform(obj):
585 glColor4f(0.5 * brightness, 0.5 * brightness, 0.5 * brightness, 0.8 * brightness)
586 self._renderObject(obj)
588 self._renderObject(obj, brightness)
589 self._objectShader.unbind()
591 glDisable(GL_STENCIL_TEST)
593 self._objectLoadShader.bind()
594 glColor4f(0.2, 0.6, 1.0, 1.0)
595 for obj in self._scene.objects():
596 if obj._loadAnim is None:
598 self._objectLoadShader.setUniform('intensity', obj._loadAnim.getPosition())
599 self._objectLoadShader.setUniform('scale', obj.getBoundaryCircle() / 10)
600 self._renderObject(obj)
601 self._objectLoadShader.unbind()
606 #Draw the object box-shadow, so you can see where it will collide with other objects.
607 if self._selectedObj is not None and len(self._scene.objects()) > 1:
608 size = self._selectedObj.getSize()[0:2] / 2 + self._scene.getObjectExtend()
610 glTranslatef(self._selectedObj.getPosition()[0], self._selectedObj.getPosition()[1], 0.0)
612 glEnable(GL_CULL_FACE)
613 glColor4f(0,0,0,0.12)
615 glVertex3f(-size[0], size[1], 0.1)
616 glVertex3f(-size[0], -size[1], 0.1)
617 glVertex3f( size[0], -size[1], 0.1)
618 glVertex3f( size[0], size[1], 0.1)
620 glDisable(GL_CULL_FACE)
623 #Draw the outline of the selected object, on top of everything else except the GUI.
624 if self._selectedObj is not None and self._selectedObj._loadAnim is None:
625 glDisable(GL_DEPTH_TEST)
626 glEnable(GL_CULL_FACE)
627 glEnable(GL_STENCIL_TEST)
629 glStencilFunc(GL_EQUAL, 0, 255)
631 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
634 self._renderObject(self._selectedObj)
635 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
637 glViewport(0, 0, self.GetSize().GetWidth(), self.GetSize().GetHeight())
638 glDisable(GL_STENCIL_TEST)
639 glDisable(GL_CULL_FACE)
640 glEnable(GL_DEPTH_TEST)
642 if self._selectedObj is not None:
644 pos = self.getObjectCenterPos()
645 glTranslate(pos[0], pos[1], pos[2])
649 def _renderObject(self, obj, brightness = False):
651 glTranslate(obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2)
653 if self.tempMatrix is not None and obj == self._selectedObj:
654 tempMatrix = opengl.convert3x3MatrixTo4x4(self.tempMatrix)
655 glMultMatrixf(tempMatrix)
657 offset = obj.getDrawOffset()
658 glTranslate(-offset[0], -offset[1], -offset[2] - obj.getSize()[2] / 2)
660 tempMatrix = opengl.convert3x3MatrixTo4x4(obj.getMatrix())
661 glMultMatrixf(tempMatrix)
664 for m in obj._meshList:
666 m.vbo = opengl.GLVBO(m.vertexes, m.normal)
668 glColor4fv(map(lambda n: n * brightness, self._objColors[n]))
673 def _drawMachine(self):
674 glEnable(GL_CULL_FACE)
677 if profile.getPreference('machine_type') == 'ultimaker':
679 self._objectShader.bind()
680 self._renderObject(self._platformMesh)
681 self._objectShader.unbind()
683 size = [profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')]
684 v0 = [ size[0] / 2, size[1] / 2, size[2]]
685 v1 = [ size[0] / 2,-size[1] / 2, size[2]]
686 v2 = [-size[0] / 2, size[1] / 2, size[2]]
687 v3 = [-size[0] / 2,-size[1] / 2, size[2]]
688 v4 = [ size[0] / 2, size[1] / 2, 0]
689 v5 = [ size[0] / 2,-size[1] / 2, 0]
690 v6 = [-size[0] / 2, size[1] / 2, 0]
691 v7 = [-size[0] / 2,-size[1] / 2, 0]
693 vList = [v0,v1,v3,v2, v1,v0,v4,v5, v2,v3,v7,v6, v0,v2,v6,v4, v3,v1,v5,v7]
694 glEnableClientState(GL_VERTEX_ARRAY)
695 glVertexPointer(3, GL_FLOAT, 3*4, vList)
697 glColor4ub(5, 171, 231, 64)
698 glDrawArrays(GL_QUADS, 0, 4)
699 glColor4ub(5, 171, 231, 96)
700 glDrawArrays(GL_QUADS, 4, 8)
701 glColor4ub(5, 171, 231, 128)
702 glDrawArrays(GL_QUADS, 12, 8)
704 sx = self._machineSize[0]
705 sy = self._machineSize[1]
706 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
707 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
712 x1 = max(min(x1, sx/2), -sx/2)
713 y1 = max(min(y1, sy/2), -sy/2)
714 x2 = max(min(x2, sx/2), -sx/2)
715 y2 = max(min(y2, sy/2), -sy/2)
716 if (x & 1) == (y & 1):
717 glColor4ub(5, 171, 231, 127)
719 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
721 glVertex3f(x1, y1, -0.02)
722 glVertex3f(x2, y1, -0.02)
723 glVertex3f(x2, y2, -0.02)
724 glVertex3f(x1, y2, -0.02)
727 glDisableClientState(GL_VERTEX_ARRAY)
729 glDisable(GL_CULL_FACE)
731 def getObjectCenterPos(self):
732 if self._selectedObj is None:
733 return [0.0, 0.0, 0.0]
734 pos = self._selectedObj.getPosition()
735 size = self._selectedObj.getSize()
736 return [pos[0], pos[1], size[2]/2]
738 def getObjectBoundaryCircle(self):
739 if self._selectedObj is None:
741 return self._selectedObj.getBoundaryCircle()
743 def getObjectSize(self):
744 if self._selectedObj is None:
745 return [0.0, 0.0, 0.0]
746 return self._selectedObj.getSize()
748 def getObjectMatrix(self):
749 if self._selectedObj is None:
750 return numpy.matrix([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
751 return self._selectedObj.getMatrix()
753 class shaderEditor(wx.Dialog):
754 def __init__(self, parent, callback, v, f):
755 super(shaderEditor, self).__init__(parent, title="Shader editor", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
756 self._callback = callback
757 s = wx.BoxSizer(wx.VERTICAL)
759 self._vertex = wx.TextCtrl(self, -1, v, style=wx.TE_MULTILINE)
760 self._fragment = wx.TextCtrl(self, -1, f, style=wx.TE_MULTILINE)
761 s.Add(self._vertex, 1, flag=wx.EXPAND)
762 s.Add(self._fragment, 1, flag=wx.EXPAND)
764 self._vertex.Bind(wx.EVT_TEXT, self.OnText, self._vertex)
765 self._fragment.Bind(wx.EVT_TEXT, self.OnText, self._fragment)
767 self.SetPosition(self.GetParent().GetPosition())
768 self.SetSize((self.GetSize().GetWidth(), self.GetParent().GetSize().GetHeight()))
772 self._callback(self._vertex.GetValue(), self._fragment.GetValue())