1 from __future__ import absolute_import
11 OpenGL.ERROR_CHECKING = False
12 from OpenGL.GLU import *
13 from OpenGL.GL import *
15 from Cura.gui import printWindow
16 from Cura.util import profile
17 from Cura.util import meshLoader
18 from Cura.util import objectScene
19 from Cura.util import resources
20 from Cura.util import sliceEngine
21 from Cura.util import machineCom
22 from Cura.util import removableStorage
23 from Cura.gui.util import previewTools
24 from Cura.gui.util import opengl
25 from Cura.gui.util import openglGui
28 def __init__(self, start, end, runTime):
31 self._startTime = time.time()
32 self._runTime = runTime
35 return time.time() > self._startTime + self._runTime
37 def getPosition(self):
40 f = (time.time() - self._startTime) / self._runTime
43 #f = 6*tc*ts + -15*ts*ts + 10*tc
45 return self._start + (self._end - self._start) * f
47 class SceneView(openglGui.glGuiPanel):
48 def __init__(self, parent):
49 super(SceneView, self).__init__(parent)
54 self._scene = objectScene.Scene()
55 self._objectShader = None
57 self._selectedObj = None
58 self._objColors = [None,None,None,None]
61 self._mouseState = None
62 self._viewTarget = numpy.array([0,0,0], numpy.float32)
65 self._platformMesh = meshLoader.loadMeshes(resources.getPathForMesh('ultimaker_platform.stl'))[0]
66 self._platformMesh._drawOffset = numpy.array([0,0,1.5], numpy.float32)
67 self._isSimpleMode = True
70 self._modelMatrix = None
71 self._projMatrix = None
72 self.tempMatrix = None
74 self.openFileButton = openglGui.glButton(self, 4, 'Load', (0,0), self.ShowLoadModel)
75 self.printButton = openglGui.glButton(self, 6, 'Print', (1,0), self.ShowPrintWindow)
76 self.printButton.setDisabled(True)
79 self.rotateToolButton = openglGui.glRadioButton(self, 8, 'Rotate', (0,-1), group, self.OnToolSelect)
80 self.scaleToolButton = openglGui.glRadioButton(self, 9, 'Scale', (1,-1), group, self.OnToolSelect)
81 self.mirrorToolButton = openglGui.glRadioButton(self, 10, 'Mirror', (2,-1), group, self.OnToolSelect)
83 self.resetRotationButton = openglGui.glButton(self, 12, 'Reset', (0,-2), self.OnRotateReset)
84 self.layFlatButton = openglGui.glButton(self, 16, 'Lay flat', (0,-3), self.OnLayFlat)
86 self.resetScaleButton = openglGui.glButton(self, 13, 'Reset', (1,-2), self.OnScaleReset)
87 self.scaleMaxButton = openglGui.glButton(self, 17, 'To max', (1,-3), self.OnScaleMax)
89 self.mirrorXButton = openglGui.glButton(self, 14, 'Mirror X', (2,-2), lambda button: self.OnMirror(0))
90 self.mirrorYButton = openglGui.glButton(self, 18, 'Mirror Y', (2,-3), lambda button: self.OnMirror(1))
91 self.mirrorZButton = openglGui.glButton(self, 22, 'Mirror Z', (2,-4), lambda button: self.OnMirror(2))
93 self.rotateToolButton.setExpandArrow(True)
94 self.scaleToolButton.setExpandArrow(True)
95 self.mirrorToolButton.setExpandArrow(True)
97 self.scaleForm = openglGui.glFrame(self, (2, -2))
98 openglGui.glGuiLayoutGrid(self.scaleForm)
99 openglGui.glLabel(self.scaleForm, 'Scale X', (0,0))
100 self.scaleXctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,0), lambda value: self.OnScaleEntry(value, 0))
101 openglGui.glLabel(self.scaleForm, 'Scale Y', (0,1))
102 self.scaleYctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,1), lambda value: self.OnScaleEntry(value, 1))
103 openglGui.glLabel(self.scaleForm, 'Scale Z', (0,2))
104 self.scaleZctrl = openglGui.glNumberCtrl(self.scaleForm, '1.0', (1,2), lambda value: self.OnScaleEntry(value, 2))
105 openglGui.glLabel(self.scaleForm, 'Size X (mm)', (0,4))
106 self.scaleXmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,4), lambda value: self.OnScaleEntryMM(value, 0))
107 openglGui.glLabel(self.scaleForm, 'Size Y (mm)', (0,5))
108 self.scaleYmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,5), lambda value: self.OnScaleEntryMM(value, 1))
109 openglGui.glLabel(self.scaleForm, 'Size Z (mm)', (0,6))
110 self.scaleZmmctrl = openglGui.glNumberCtrl(self.scaleForm, '0.0', (1,6), lambda value: self.OnScaleEntryMM(value, 2))
111 openglGui.glLabel(self.scaleForm, 'Uniform scale', (0,8))
112 self.scaleUniform = openglGui.glCheckbox(self.scaleForm, True, (1,8), None)
114 self._slicer = sliceEngine.Slicer(self._updateSliceProgress)
115 self._sceneUpdateTimer = wx.Timer(self)
116 self.Bind(wx.EVT_TIMER, lambda e : self._slicer.runSlicer(self._scene), self._sceneUpdateTimer)
117 self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
120 self.updateProfileToControls()
121 wx.EVT_IDLE(self, self.OnIdle)
123 def ShowLoadModel(self, button):
125 dlg=wx.FileDialog(self, 'Open 3D model', os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST)
126 dlg.SetWildcard(meshLoader.wildcardFilter())
127 if dlg.ShowModal() != wx.ID_OK:
130 filename = dlg.GetPath()
132 if not(os.path.exists(filename)):
134 profile.putPreference('lastFile', filename)
135 self.GetParent().GetParent().GetParent().addToModelMRU(filename)
136 self.loadScene([filename])
138 def ShowPrintWindow(self, button):
140 if machineCom.machineIsConnected():
141 printWindow.printFile(self._slicer.getGCodeFilename())
142 elif len(removableStorage.getPossibleSDcardDrives()) > 0:
143 drives = removableStorage.getPossibleSDcardDrives()
148 filename = os.path.basename(profile.getPreference('lastFile'))
149 filename = filename[0:filename.rfind('.')] + '.gcode'
150 shutil.copy(self._slicer.getGCodeFilename(), drive[1] + filename)
152 defPath = profile.getPreference('lastFile')
153 defPath = defPath[0:defPath.rfind('.')] + '.gcode'
154 dlg=wx.FileDialog(self, 'Save toolpath', defPath, style=wx.FD_SAVE)
155 dlg.SetFilename(defPath)
156 dlg.SetWildcard('Toolpath (*.gcode)|*.gcode;*.g')
157 if dlg.ShowModal() != wx.ID_OK:
160 filename = dlg.GetPath()
163 shutil.copy(self._slicer.getGCodeFilename(), filename)
166 if self._animView is not None or self._animZoom is not None:
169 for obj in self._scene.objects():
170 if obj._loadAnim is not None:
174 def OnToolSelect(self, button):
175 if self.rotateToolButton.getSelected():
176 self.tool = previewTools.toolRotate(self)
177 elif self.scaleToolButton.getSelected():
178 self.tool = previewTools.toolScale(self)
179 elif self.mirrorToolButton.getSelected():
180 self.tool = previewTools.toolNone(self)
182 self.tool = previewTools.toolNone(self)
183 self.resetRotationButton.setHidden(not self.rotateToolButton.getSelected())
184 self.layFlatButton.setHidden(not self.rotateToolButton.getSelected())
185 self.resetScaleButton.setHidden(not self.scaleToolButton.getSelected())
186 self.scaleMaxButton.setHidden(not self.scaleToolButton.getSelected())
187 self.scaleForm.setHidden(not self.scaleToolButton.getSelected())
188 self.mirrorXButton.setHidden(not self.mirrorToolButton.getSelected())
189 self.mirrorYButton.setHidden(not self.mirrorToolButton.getSelected())
190 self.mirrorZButton.setHidden(not self.mirrorToolButton.getSelected())
192 def OnRotateReset(self, button):
193 if self._selectedObj is None:
197 def OnLayFlat(self, button):
198 if self._selectedObj is None:
202 def OnScaleReset(self, button):
203 if self._selectedObj is None:
207 def OnScaleMax(self, button):
208 if self._selectedObj is None:
212 def OnMirror(self, axis):
213 if self._selectedObj is None:
215 self._selectedObj.mirror(axis)
217 def sceneUpdated(self):
218 self._sceneUpdateTimer.Start(1, True)
219 self._slicer.abortSlicer()
220 self._scene.setSizeOffsets(numpy.array(profile.calculateObjectSizeOffsets(), numpy.float32))
223 def _updateSliceProgress(self, progressValue, ready):
224 self.printButton.setDisabled(not ready)
225 self.printButton.setProgressBar(progressValue)
228 def loadScene(self, fileList):
229 for filename in fileList:
231 objList = meshLoader.loadMeshes(filename)
233 traceback.print_exc()
236 obj._loadAnim = anim(1, 0, 1.5)
238 self._scene.centerAll()
239 self._selectObject(obj)
242 def _deleteObject(self, obj):
243 if obj == self._selectedObj:
244 self._selectedObj = None
245 if obj == self._focusObj:
246 self._focusObj = None
247 self._scene.remove(obj)
248 for m in obj._meshList:
249 if m.vbo is not None:
250 self.glReleaseList.append(m.vbo)
251 if self._isSimpleMode:
252 self._scene.arrangeAll()
255 def _selectObject(self, obj, zoom = True):
256 if obj != self._selectedObj:
257 self._selectedObj = obj
258 scale = self._selectedObj.getScale()
259 size = self._selectedObj.getSize()
260 self.scaleXctrl.setValue(round(scale[0], 2))
261 self.scaleYctrl.setValue(round(scale[1], 2))
262 self.scaleZctrl.setValue(round(scale[2], 2))
263 self.scaleXmmctrl.setValue(round(size[0], 2))
264 self.scaleYmmctrl.setValue(round(size[1], 2))
265 self.scaleZmmctrl.setValue(round(size[2], 2))
267 newViewPos = numpy.array([obj.getPosition()[0], obj.getPosition()[1], obj.getMaximum()[2] / 2])
268 self._animView = anim(self._viewTarget.copy(), newViewPos, 0.5)
269 newZoom = obj.getBoundaryCircle() * 6
270 if newZoom > numpy.max(self._machineSize) * 3:
271 newZoom = numpy.max(self._machineSize) * 3
272 self._animZoom = anim(self._zoom, newZoom, 0.5)
274 def updateProfileToControls(self):
275 oldSimpleMode = self._isSimpleMode
276 self._isSimpleMode = profile.getPreference('startMode') == 'Simple'
277 if self._isSimpleMode and not oldSimpleMode:
278 self._scene.arrangeAll()
280 self._machineSize = numpy.array([profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')])
281 self._objColors[0] = profile.getPreferenceColour('model_colour')
282 self._objColors[1] = profile.getPreferenceColour('model_colour2')
283 self._objColors[2] = profile.getPreferenceColour('model_colour3')
284 self._objColors[3] = profile.getPreferenceColour('model_colour4')
285 self._scene.setMachineSize(self._machineSize)
287 def OnKeyChar(self, keyCode):
288 if keyCode == wx.WXK_DELETE or keyCode == wx.WXK_NUMPAD_DELETE:
289 if self._selectedObj is not None:
290 self._deleteObject(self._selectedObj)
293 if keyCode == wx.WXK_F3 and wx.GetKeyState(wx.WXK_SHIFT):
294 shaderEditor(self, self.ShaderUpdate, self._objectLoadShader.getVertexShader(), self._objectLoadShader.getFragmentShader())
296 def ShaderUpdate(self, v, f):
297 s = opengl.GLShader(v, f)
299 self._objectLoadShader.release()
300 self._objectLoadShader = s
301 for obj in self._scene.objects():
302 obj._loadAnim = anim(1, 0, 1.5)
305 def OnMouseDown(self,e):
306 self._mouseX = e.GetX()
307 self._mouseY = e.GetY()
308 self._mouseClick3DPos = self._mouse3Dpos
309 self._mouseClickFocus = self._focusObj
311 self._mouseState = 'doubleClick'
313 self._mouseState = 'dragOrClick'
314 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
315 p0 -= self.getObjectCenterPos() - self._viewTarget
316 p1 -= self.getObjectCenterPos() - self._viewTarget
317 if self.tool.OnDragStart(p0, p1):
318 self._mouseState = 'tool'
319 if self._mouseState == 'dragOrClick':
320 if e.GetButton() == 1:
321 if self._focusObj is not None:
322 self._selectObject(self._focusObj, False)
325 def OnMouseUp(self, e):
326 if e.LeftIsDown() or e.MiddleIsDown() or e.RightIsDown():
328 if self._mouseState == 'dragOrClick':
329 if e.GetButton() == 1:
330 if self._focusObj is not None:
331 self._selectObject(self._focusObj)
333 self._selectedObj = None
335 if e.GetButton() == 3 and self._selectedObj == self._focusObj:
337 #menu.Append(-1, 'Test')
338 #self.PopupMenu(menu)
341 elif self._mouseState == 'dragObject' and self._selectedObj is not None:
342 self._scene.pushFree()
344 elif self._mouseState == 'tool':
345 if self.tempMatrix is not None and self._selectedObj is not None:
346 self._selectedObj.applyMatrix(self.tempMatrix)
347 self.tempMatrix = None
348 self.tool.OnDragEnd()
350 self._mouseState = None
352 def OnMouseMotion(self,e):
353 p0, p1 = self.getMouseRay(e.GetX(), e.GetY())
354 p0 -= self.getObjectCenterPos() - self._viewTarget
355 p1 -= self.getObjectCenterPos() - self._viewTarget
357 if e.Dragging() and self._mouseState is not None:
358 if self._mouseState == 'tool':
359 self.tool.OnDrag(p0, p1)
360 elif not e.LeftIsDown() and e.RightIsDown():
361 self._yaw += e.GetX() - self._mouseX
362 self._pitch -= e.GetY() - self._mouseY
363 if self._pitch > 170:
367 elif (e.LeftIsDown() and e.RightIsDown()) or e.MiddleIsDown():
368 self._zoom += e.GetY() - self._mouseY
371 if self._zoom > numpy.max(self._machineSize) * 3:
372 self._zoom = numpy.max(self._machineSize) * 3
373 elif e.LeftIsDown() and self._selectedObj is not None and self._selectedObj == self._mouseClickFocus and not self._isSimpleMode:
374 self._mouseState = 'dragObject'
375 z = max(0, self._mouseClick3DPos[2])
376 p0, p1 = self.getMouseRay(self._mouseX, self._mouseY)
377 p2, p3 = self.getMouseRay(e.GetX(), e.GetY())
382 cursorZ0 = p0 - (p1 - p0) * (p0[2] / (p1[2] - p0[2]))
383 cursorZ1 = p2 - (p3 - p2) * (p2[2] / (p3[2] - p2[2]))
384 diff = cursorZ1 - cursorZ0
385 self._selectedObj.setPosition(self._selectedObj.getPosition() + diff[0:2])
386 if not e.Dragging() or self._mouseState != 'tool':
387 self.tool.OnMouseMove(p0, p1)
389 self._mouseX = e.GetX()
390 self._mouseY = e.GetY()
392 def OnMouseWheel(self, e):
393 self._zoom *= 1.0 - float(e.GetWheelRotation() / e.GetWheelDelta()) / 10.0
396 if self._zoom > numpy.max(self._machineSize) * 3:
397 self._zoom = numpy.max(self._machineSize) * 3
400 def getMouseRay(self, x, y):
401 if self._viewport is None:
402 return numpy.array([0,0,0],numpy.float32), numpy.array([0,0,1],numpy.float32)
403 p0 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 0, self._modelMatrix, self._projMatrix, self._viewport)
404 p1 = opengl.unproject(x, self._viewport[1] + self._viewport[3] - y, 1, self._modelMatrix, self._projMatrix, self._viewport)
405 p0 -= self._viewTarget
406 p1 -= self._viewTarget
409 def _init3DView(self):
410 # set viewing projection
411 size = self.GetSize()
412 glViewport(0, 0, size.GetWidth(), size.GetHeight())
415 glLightfv(GL_LIGHT0, GL_POSITION, [0.2, 0.2, 1.0, 0.0])
417 glDisable(GL_RESCALE_NORMAL)
418 glDisable(GL_LIGHTING)
420 glEnable(GL_DEPTH_TEST)
421 glDisable(GL_CULL_FACE)
423 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
425 glClearColor(0.8, 0.8, 0.8, 1.0)
429 glMatrixMode(GL_PROJECTION)
431 aspect = float(size.GetWidth()) / float(size.GetHeight())
432 gluPerspective(45.0, aspect, 1.0, numpy.max(self._machineSize) * 4)
434 glMatrixMode(GL_MODELVIEW)
436 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
439 if machineCom.machineIsConnected():
440 self.printButton._imageID = 6
441 self.printButton._tooltip = 'Print'
442 elif len(removableStorage.getPossibleSDcardDrives()) > 0:
443 self.printButton._imageID = 2
444 self.printButton._tooltip = 'Toolpath to SD'
446 self.printButton._imageID = 3
447 self.printButton._tooltip = 'Save toolpath'
449 if self._animView is not None:
450 self._viewTarget = self._animView.getPosition()
451 if self._animView.isDone():
452 self._animView = None
453 if self._animZoom is not None:
454 self._zoom = self._animZoom.getPosition()
455 if self._animZoom.isDone():
456 self._animZoom = None
457 if self._objectShader is None:
458 self._objectShader = opengl.GLShader("""
459 varying float light_amount;
463 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
464 gl_FrontColor = gl_Color;
466 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
470 varying float light_amount;
474 gl_FragColor = vec4(gl_Color.xyz * light_amount, gl_Color[3]);
477 self._objectLoadShader = opengl.GLShader("""
478 uniform float intensity;
480 varying float light_amount;
484 vec4 tmp = gl_Vertex;
485 tmp.x += sin(tmp.z/5.0+intensity*30.0) * scale * intensity;
486 tmp.y += sin(tmp.z/3.0+intensity*40.0) * scale * intensity;
487 gl_Position = gl_ModelViewProjectionMatrix * tmp;
488 gl_FrontColor = gl_Color;
490 light_amount = abs(dot(normalize(gl_NormalMatrix * gl_Normal), normalize(gl_LightSource[0].position.xyz)));
494 uniform float intensity;
495 varying float light_amount;
499 gl_FragColor = vec4(gl_Color.xyz * light_amount, 1.0-intensity);
503 glTranslate(0,0,-self._zoom)
504 glRotate(-self._pitch, 1,0,0)
505 glRotate(self._yaw, 0,0,1)
506 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
508 self._viewport = glGetIntegerv(GL_VIEWPORT)
509 self._modelMatrix = glGetDoublev(GL_MODELVIEW_MATRIX)
510 self._projMatrix = glGetDoublev(GL_PROJECTION_MATRIX)
512 glClearColor(1,1,1,1)
513 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)
515 for n in xrange(0, len(self._scene.objects())):
516 obj = self._scene.objects()[n]
517 glColor4ub((n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >> 8) & 0xFF, n & 0xFF)
518 self._renderObject(obj)
520 if self._mouseX > -1:
521 n = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8)[0][0]
522 if n < len(self._scene.objects()):
523 self._focusObj = self._scene.objects()[n]
525 self._focusObj = None
526 f = glReadPixels(self._mouseX, self.GetSize().GetHeight() - 1 - self._mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0]
527 self._mouse3Dpos = opengl.unproject(self._mouseX, self._viewport[1] + self._viewport[3] - self._mouseY, f, self._modelMatrix, self._projMatrix, self._viewport)
528 self._mouse3Dpos -= self._viewTarget
531 glTranslate(0,0,-self._zoom)
532 glRotate(-self._pitch, 1,0,0)
533 glRotate(self._yaw, 0,0,1)
534 glTranslate(-self._viewTarget[0],-self._viewTarget[1],-self._viewTarget[2])
536 glStencilFunc(GL_ALWAYS, 1, 1)
537 glStencilOp(GL_INCR, GL_INCR, GL_INCR)
538 self._objectShader.bind()
539 for obj in self._scene.objects():
540 if obj._loadAnim is not None:
541 if obj._loadAnim.isDone():
545 col = self._objColors[0]
546 if not self._scene.checkPlatform(obj):
547 col = [0.5,0.5,0.5,0.8]
548 glDisable(GL_STENCIL_TEST)
549 if self._selectedObj == obj:
550 glEnable(GL_STENCIL_TEST)
551 if self._focusObj == obj:
552 col = map(lambda n: n * 1.2, col)
553 elif self._focusObj is not None or self._selectedObj is not None and obj != self._selectedObj:
554 col = map(lambda n: n * 0.8, col)
555 glColor4f(col[0], col[1], col[2], col[3])
556 self._renderObject(obj)
557 self._objectShader.unbind()
559 glDisable(GL_STENCIL_TEST)
561 self._objectLoadShader.bind()
562 glColor4f(0.2, 0.6, 1.0, 1.0)
563 for obj in self._scene.objects():
564 if obj._loadAnim is None:
566 self._objectLoadShader.setUniform('intensity', obj._loadAnim.getPosition())
567 self._objectLoadShader.setUniform('scale', obj.getBoundaryCircle() / 10)
568 self._renderObject(obj)
569 self._objectLoadShader.unbind()
574 #Draw the object box-shadow, so you can see where it will collide with other objects.
575 if self._selectedObj is not None and len(self._scene.objects()) > 1:
576 size = self._selectedObj.getSize()[0:2] / 2 + self._scene.getObjectExtend()
578 glTranslatef(self._selectedObj.getPosition()[0], self._selectedObj.getPosition()[1], 0.0)
580 glEnable(GL_CULL_FACE)
581 glColor4f(0,0,0,0.12)
583 glVertex3f(-size[0], size[1], 0)
584 glVertex3f(-size[0], -size[1], 0)
585 glVertex3f( size[0], -size[1], 0)
586 glVertex3f( size[0], size[1], 0)
588 glDisable(GL_CULL_FACE)
591 #Draw the outline of the selected object, on top of everything else except the GUI.
592 if self._selectedObj is not None and self._selectedObj._loadAnim is None:
593 glDisable(GL_DEPTH_TEST)
594 glEnable(GL_CULL_FACE)
595 glEnable(GL_STENCIL_TEST)
596 glStencilFunc(GL_EQUAL, 0, 255)
598 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
601 self._renderObject(self._selectedObj)
602 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
604 glViewport(0, 0, self.GetSize().GetWidth(), self.GetSize().GetHeight())
605 glDisable(GL_STENCIL_TEST)
606 glDisable(GL_CULL_FACE)
607 glEnable(GL_DEPTH_TEST)
609 if self._selectedObj is not None:
611 pos = self.getObjectCenterPos()
612 glTranslate(pos[0], pos[1], pos[2])
616 def _renderObject(self, obj):
618 glTranslate(obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2)
620 if self.tempMatrix is not None and obj == self._selectedObj:
621 tempMatrix = opengl.convert3x3MatrixTo4x4(self.tempMatrix)
622 glMultMatrixf(tempMatrix)
624 offset = obj.getDrawOffset()
625 glTranslate(-offset[0], -offset[1], -offset[2] - obj.getSize()[2] / 2)
627 tempMatrix = opengl.convert3x3MatrixTo4x4(obj.getMatrix())
628 glMultMatrixf(tempMatrix)
630 for m in obj._meshList:
632 m.vbo = opengl.GLVBO(m.vertexes, m.normal)
636 def _drawMachine(self):
637 glEnable(GL_CULL_FACE)
640 if profile.getPreference('machine_type') == 'ultimaker':
642 self._objectShader.bind()
643 self._renderObject(self._platformMesh)
644 self._objectShader.unbind()
646 size = [profile.getPreferenceFloat('machine_width'), profile.getPreferenceFloat('machine_depth'), profile.getPreferenceFloat('machine_height')]
647 v0 = [ size[0] / 2, size[1] / 2, size[2]]
648 v1 = [ size[0] / 2,-size[1] / 2, size[2]]
649 v2 = [-size[0] / 2, size[1] / 2, size[2]]
650 v3 = [-size[0] / 2,-size[1] / 2, size[2]]
651 v4 = [ size[0] / 2, size[1] / 2, 0]
652 v5 = [ size[0] / 2,-size[1] / 2, 0]
653 v6 = [-size[0] / 2, size[1] / 2, 0]
654 v7 = [-size[0] / 2,-size[1] / 2, 0]
656 vList = [v0,v1,v3,v2, v1,v0,v4,v5, v2,v3,v7,v6, v0,v2,v6,v4, v3,v1,v5,v7]
657 glEnableClientState(GL_VERTEX_ARRAY)
658 glVertexPointer(3, GL_FLOAT, 3*4, vList)
660 glColor4ub(5, 171, 231, 64)
661 glDrawArrays(GL_QUADS, 0, 4)
662 glColor4ub(5, 171, 231, 96)
663 glDrawArrays(GL_QUADS, 4, 8)
664 glColor4ub(5, 171, 231, 128)
665 glDrawArrays(GL_QUADS, 12, 8)
667 sx = self._machineSize[0]
668 sy = self._machineSize[1]
669 for x in xrange(-int(sx/20)-1, int(sx / 20) + 1):
670 for y in xrange(-int(sx/20)-1, int(sy / 20) + 1):
675 x1 = max(min(x1, sx/2), -sx/2)
676 y1 = max(min(y1, sy/2), -sy/2)
677 x2 = max(min(x2, sx/2), -sx/2)
678 y2 = max(min(y2, sy/2), -sy/2)
679 if (x & 1) == (y & 1):
680 glColor4ub(5, 171, 231, 127)
682 glColor4ub(5 * 8 / 10, 171 * 8 / 10, 231 * 8 / 10, 128)
684 glVertex3f(x1, y1, -0.02)
685 glVertex3f(x2, y1, -0.02)
686 glVertex3f(x2, y2, -0.02)
687 glVertex3f(x1, y2, -0.02)
690 glDisableClientState(GL_VERTEX_ARRAY)
692 glDisable(GL_CULL_FACE)
694 def getObjectCenterPos(self):
695 if self._selectedObj is None:
696 return [0.0, 0.0, 0.0]
697 pos = self._selectedObj.getPosition()
698 size = self._selectedObj.getSize()
699 return [pos[0], pos[1], size[2]/2]
701 def getObjectBoundaryCircle(self):
702 if self._selectedObj is None:
704 return self._selectedObj.getBoundaryCircle()
706 def getObjectSize(self):
707 if self._selectedObj is None:
708 return [0.0, 0.0, 0.0]
709 return self._selectedObj.getSize()
711 def getObjectMatrix(self):
712 if self._selectedObj is None:
713 return numpy.matrix([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
714 return self._selectedObj.getMatrix()
716 class shaderEditor(wx.Dialog):
717 def __init__(self, parent, callback, v, f):
718 super(shaderEditor, self).__init__(parent, title="Shader editor", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
719 self._callback = callback
720 s = wx.BoxSizer(wx.VERTICAL)
722 self._vertex = wx.TextCtrl(self, -1, v, style=wx.TE_MULTILINE)
723 self._fragment = wx.TextCtrl(self, -1, f, style=wx.TE_MULTILINE)
724 s.Add(self._vertex, 1, flag=wx.EXPAND)
725 s.Add(self._fragment, 1, flag=wx.EXPAND)
727 self._vertex.Bind(wx.EVT_TEXT, self.OnText, self._vertex)
728 self._fragment.Bind(wx.EVT_TEXT, self.OnText, self._fragment)
730 self.SetPosition(self.GetParent().GetPosition())
731 self.SetSize((self.GetSize().GetWidth(), self.GetParent().GetSize().GetHeight()))
735 self._callback(self._vertex.GetValue(), self._fragment.GetValue())