From 90a1f5f8edc5ce264b24ab0b99e0ad3af5961cde Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 3 Aug 2016 14:04:33 +0200 Subject: [PATCH 01/11] Revert "Revert "Show "ghosts" for all objects on the buildplate in layerview"" This reverts commit 0f9b989ae86fa319269a715d960b533f2a51c09d. --- plugins/LayerView/LayerView.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 801f4797dd..7956e35d2a 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -86,8 +86,7 @@ class LayerView(View): if not self._ghost_shader: self._ghost_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader")) - self._ghost_shader.setUniformValue("u_color", Color(0, 0, 0, 64)) - + self._ghost_shader.setUniformValue("u_color", Color(32, 32, 32, 96)) for node in DepthFirstIterator(scene.getRoot()): # We do not want to render ConvexHullNode as it conflicts with the bottom layers. # However, it is somewhat relevant when the node is selected, so do render it then. @@ -96,13 +95,7 @@ class LayerView(View): if not node.render(renderer): if node.getMeshData() and node.isVisible(): - renderer.queueNode(node, - shader = self._ghost_shader, - type = RenderBatch.RenderType.Transparent ) - - for node in DepthFirstIterator(scene.getRoot()): - if type(node) is SceneNode: - if node.getMeshData() and node.isVisible(): + renderer.queueNode(node, transparent = True, shader = self._ghost_shader) layer_data = node.callDecoration("getLayerData") if not layer_data: continue @@ -118,13 +111,13 @@ class LayerView(View): end += counts # This uses glDrawRangeElements internally to only draw a certain range of lines. - renderer.queueNode(node, mesh = layer_data, mode = RenderBatch.RenderMode.Lines, range = (start, end)) + renderer.queueNode(node, mesh = layer_data, mode = RenderBatch.RenderMode.Lines, overlay = True, range = (start, end)) if self._current_layer_mesh: - renderer.queueNode(node, mesh = self._current_layer_mesh) + renderer.queueNode(node, mesh = self._current_layer_mesh, overlay = True) if self._current_layer_jumps: - renderer.queueNode(node, mesh = self._current_layer_jumps) + renderer.queueNode(node, mesh = self._current_layer_jumps, overlay = True) def setLayer(self, value): if self._current_layer_num != value: From b090eab2216af45e500dc9388d152a3224db54d8 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 2 Aug 2016 14:31:17 +0200 Subject: [PATCH 02/11] Use renderpass to render layers above ghosts CURA-1601 --- plugins/LayerView/LayerPass.py | 86 ++++++++++++++++++++ plugins/LayerView/LayerView.py | 60 ++++++++------ plugins/LayerView/layerview_composite.shader | 80 ++++++++++++++++++ 3 files changed, 203 insertions(+), 23 deletions(-) create mode 100644 plugins/LayerView/LayerPass.py create mode 100644 plugins/LayerView/layerview_composite.shader diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py new file mode 100644 index 0000000000..83ce60ffd1 --- /dev/null +++ b/plugins/LayerView/LayerPass.py @@ -0,0 +1,86 @@ +# Copyright (c) 2015 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + +from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator +from UM.Resources import Resources +from UM.Scene.SceneNode import SceneNode +from UM.Scene.ToolHandle import ToolHandle +from UM.Application import Application + +from UM.View.RenderPass import RenderPass +from UM.View.RenderBatch import RenderBatch +from UM.View.GL.OpenGL import OpenGL + +## RenderPass used to display g-code paths. +class LayerPass(RenderPass): + def __init__(self, width, height): + super().__init__("layerview", width, height) + + self._shader = None + self._tool_handle_shader = None + self._gl = OpenGL.getInstance().getBindingsObject() + self._scene = Application.getInstance().getController().getScene() + + self._layerview = None + + def setLayerView(self, layerview): + self._layerview = layerview + + def render(self): + if not self._shader: + self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader")) + if not self._tool_handle_shader: + self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader")) + + self.bind() + self._gl.glDisable(self._gl.GL_DEPTH_TEST) + + tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay) + tool_handle_has_items = False + + for node in DepthFirstIterator(self._scene.getRoot()): + if isinstance(node, ToolHandle): + tool_handle_batch.addItem(node.getWorldTransformation(), mesh = node.getSolidMesh()) + tool_handle_has_items = True + + if type(node) is SceneNode and node.getMeshData() and node.isVisible(): + layer_data = node.callDecoration("getLayerData") + if not layer_data: + continue + + # Render all layers below a certain number as line mesh instead of vertices. + if self._layerview._current_layer_num - self._layerview._solid_layers > -1 and not self._layerview._only_show_top_layers: + start = 0 + end = 0 + element_counts = layer_data.getElementCounts() + for layer, counts in element_counts.items(): + if layer + self._layerview._solid_layers > self._layerview._current_layer_num: + break + end += counts + + # This uses glDrawRangeElements internally to only draw a certain range of lines. + batch = RenderBatch(self._shader, type = RenderBatch.RenderType.NoType, mode = RenderBatch.RenderMode.Lines, range = (start, end)) + batch.addItem(node.getWorldTransformation(), layer_data) + batch.render(self._scene.getActiveCamera()) + + # Create a new batch that is not range-limited + batch = RenderBatch(self._shader, type = RenderBatch.RenderType.NoType, mode = RenderBatch.RenderMode.Lines) + batch_has_items = False + + if self._layerview._current_layer_mesh: + batch_has_items = True + batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_mesh) + + if self._layerview._current_layer_jumps: + batch_has_items = True + batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_jumps) + + if batch_has_items: + batch.render(self._scene.getActiveCamera()) + + # Render toolhandles on top of the layerview + if tool_handle_has_items: + tool_handle_batch.render(self._scene.getActiveCamera()) + + self._gl.glEnable(self._gl.GL_DEPTH_TEST) + self.release() diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 7956e35d2a..c7354e52be 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -1,6 +1,7 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. +from UM.PluginRegistry import PluginRegistry from UM.View.View import View from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Resources import Resources @@ -26,14 +27,16 @@ from . import LayerViewProxy from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") +from . import LayerPass + import numpy +import os.path ## View used to display g-code paths. class LayerView(View): def __init__(self): super().__init__() self._shader = None - self._ghost_shader = None self._num_layers = 0 self._layer_percentage = 0 # what percentage of layers need to be shown (Slider gives value between 0 - 100) self._proxy = LayerViewProxy.LayerViewProxy() @@ -46,6 +49,13 @@ class LayerView(View): self._activity = False self._old_max_layers = 0 + self._ghost_shader = None + self._ghost_pass = None + self._composite_pass = None + self._old_layer_bindings = None + self._layerview_composite_shader = None + self._old_composite_shader = None + Preferences.getInstance().addPreference("view/top_layer_count", 5) Preferences.getInstance().addPreference("view/only_show_top_layers", False) Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged) @@ -87,6 +97,7 @@ class LayerView(View): if not self._ghost_shader: self._ghost_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader")) self._ghost_shader.setUniformValue("u_color", Color(32, 32, 32, 96)) + for node in DepthFirstIterator(scene.getRoot()): # We do not want to render ConvexHullNode as it conflicts with the bottom layers. # However, it is somewhat relevant when the node is selected, so do render it then. @@ -96,28 +107,6 @@ class LayerView(View): if not node.render(renderer): if node.getMeshData() and node.isVisible(): renderer.queueNode(node, transparent = True, shader = self._ghost_shader) - layer_data = node.callDecoration("getLayerData") - if not layer_data: - continue - - # Render all layers below a certain number as line mesh instead of vertices. - if self._current_layer_num - self._solid_layers > -1 and not self._only_show_top_layers: - start = 0 - end = 0 - element_counts = layer_data.getElementCounts() - for layer, counts in element_counts.items(): - if layer + self._solid_layers > self._current_layer_num: - break - end += counts - - # This uses glDrawRangeElements internally to only draw a certain range of lines. - renderer.queueNode(node, mesh = layer_data, mode = RenderBatch.RenderMode.Lines, overlay = True, range = (start, end)) - - if self._current_layer_mesh: - renderer.queueNode(node, mesh = self._current_layer_mesh, overlay = True) - - if self._current_layer_jumps: - renderer.queueNode(node, mesh = self._current_layer_jumps, overlay = True) def setLayer(self, value): if self._current_layer_num != value: @@ -182,6 +171,31 @@ class LayerView(View): self.setLayer(self._current_layer_num - 1) return True + if event.type == Event.ViewActivateEvent: + if not self._ghost_pass: + # Currently the RenderPass constructor requires a size > 0 + # This should be fixed in RenderPass's constructor. + self._ghost_pass = LayerPass.LayerPass(1, 1) + self._ghost_pass.setLayerView(self) + self.getRenderer().addRenderPass(self._ghost_pass) + + if not self._layerview_composite_shader: + self._layerview_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("LayerView"), "layerview_composite.shader")) + + if not self._composite_pass: + self._composite_pass = self.getRenderer().getRenderPass("composite") + + self._old_layer_bindings = self._composite_pass.getLayerBindings() + layer_bindings = self._old_layer_bindings[:] # make a copy + layer_bindings.append("layerview") + self._composite_pass.setLayerBindings(layer_bindings) + self._old_composite_shader = self._composite_pass.getCompositeShader() + self._composite_pass.setCompositeShader(self._layerview_composite_shader) + + if event.type == Event.ViewDeactivateEvent: + self._composite_pass.setLayerBindings(self._old_layer_bindings) + self._composite_pass.setCompositeShader(self._old_composite_shader) + def _startUpdateTopLayers(self): if self._top_layers_job: self._top_layers_job.finished.disconnect(self._updateCurrentLayerMesh) diff --git a/plugins/LayerView/layerview_composite.shader b/plugins/LayerView/layerview_composite.shader new file mode 100644 index 0000000000..aad251f852 --- /dev/null +++ b/plugins/LayerView/layerview_composite.shader @@ -0,0 +1,80 @@ +[shaders] +vertex = + uniform highp mat4 u_modelViewProjectionMatrix; + attribute highp vec4 a_vertex; + attribute highp vec2 a_uvs; + + varying highp vec2 v_uvs; + + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + v_uvs = a_uvs; + } + +fragment = + uniform sampler2D u_layer0; + uniform sampler2D u_layer1; + uniform sampler2D u_layer2; + uniform sampler2D u_layer3; + + uniform float u_imageWidth; + uniform float u_imageHeight; + + uniform vec2 u_offset[9]; + + uniform float u_outline_strength; + uniform vec4 u_outline_color; + + varying vec2 v_uvs; + + float kernel[9]; + + const vec3 x_axis = vec3(1.0, 0.0, 0.0); + const vec3 y_axis = vec3(0.0, 1.0, 0.0); + const vec3 z_axis = vec3(0.0, 0.0, 1.0); + + void main() + { + kernel[0] = 0.0; kernel[1] = 1.0; kernel[2] = 0.0; + kernel[3] = 1.0; kernel[4] = -4.0; kernel[5] = 1.0; + kernel[6] = 0.0; kernel[7] = 1.0; kernel[8] = 0.0; + + vec4 result = vec4(0.965, 0.965, 0.965, 1.0); + vec4 layer0 = texture2D(u_layer0, v_uvs); + vec4 layer2 = texture2D(u_layer2, v_uvs); + + result = layer0 * layer0.a + result * (1.0 - layer0.a); + result = layer2 * layer2.a + result * (1.0 - layer2.a); + + vec4 sum = vec4(0.0); + for (int i = 0; i < 9; i++) + { + vec4 color = vec4(texture2D(u_layer1, v_uvs.xy + u_offset[i]).a); + sum += color * (kernel[i] / u_outline_strength); + } + + vec4 layer1 = texture2D(u_layer1, v_uvs); + if((layer1.rgb == x_axis || layer1.rgb == y_axis || layer1.rgb == z_axis)) + { + gl_FragColor = result; + } + else + { + gl_FragColor = mix(result, u_outline_color, abs(sum.a)); + } + } + +[defaults] +u_layer0 = 0 +u_layer1 = 1 +u_layer2 = 2 +u_layer3 = 3 +u_outline_strength = 1.0 +u_outline_color = [0.05, 0.66, 0.89, 1.0] + +[bindings] + +[attributes] +a_vertex = vertex +a_uvs = uv From 2c35f0196d27337fb84203b6e5a64a0f0c95cf8f Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 3 Aug 2016 14:20:31 +0200 Subject: [PATCH 03/11] Code cleanup CURA-1601 --- plugins/LayerView/LayerView.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index c7354e52be..e4c216ee85 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -36,9 +36,6 @@ import os.path class LayerView(View): def __init__(self): super().__init__() - self._shader = None - self._num_layers = 0 - self._layer_percentage = 0 # what percentage of layers need to be shown (Slider gives value between 0 - 100) self._proxy = LayerViewProxy.LayerViewProxy() self._controller.getScene().getRoot().childrenChanged.connect(self._onSceneChanged) self._max_layers = 0 @@ -50,7 +47,7 @@ class LayerView(View): self._old_max_layers = 0 self._ghost_shader = None - self._ghost_pass = None + self._layer_pass = None self._composite_pass = None self._old_layer_bindings = None self._layerview_composite_shader = None @@ -172,12 +169,12 @@ class LayerView(View): return True if event.type == Event.ViewActivateEvent: - if not self._ghost_pass: + if not self._layer_pass: # Currently the RenderPass constructor requires a size > 0 # This should be fixed in RenderPass's constructor. - self._ghost_pass = LayerPass.LayerPass(1, 1) - self._ghost_pass.setLayerView(self) - self.getRenderer().addRenderPass(self._ghost_pass) + self._layer_pass = LayerPass.LayerPass(1, 1) + self._layer_pass.setLayerView(self) + self.getRenderer().addRenderPass(self._layer_pass) if not self._layerview_composite_shader: self._layerview_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("LayerView"), "layerview_composite.shader")) From 17b12b904809cae093aa59cfdd2e5958978eb6e0 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 3 Aug 2016 15:00:54 +0200 Subject: [PATCH 04/11] Move layer data into LayerPass for cleaner access CURA-1601 --- .../ProcessSlicedLayersJob.py | 2 +- plugins/LayerView/LayerPass.py | 204 ++++++++++++++++-- plugins/LayerView/LayerView.py | 182 +--------------- plugins/LayerView/LayerViewProxy.py | 12 +- 4 files changed, 204 insertions(+), 196 deletions(-) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 7443340c5b..f11df837b1 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -163,7 +163,7 @@ class ProcessSlicedLayersJob(Job): view = Application.getInstance().getController().getActiveView() if view.getPluginId() == "LayerView": - view.resetLayerData() + view.getLayerPass().resetLayerData() if self._progress: self._progress.hide() diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index 83ce60ffd1..e14bab996a 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -1,30 +1,112 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. -from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator +from UM.Logger import Logger +from UM.Application import Application from UM.Resources import Resources +from UM.Preferences import Preferences +from UM.Signal import Signal +from UM.Job import Job + +from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.SceneNode import SceneNode from UM.Scene.ToolHandle import ToolHandle -from UM.Application import Application - +from UM.Mesh.MeshBuilder import MeshBuilder from UM.View.RenderPass import RenderPass from UM.View.RenderBatch import RenderBatch from UM.View.GL.OpenGL import OpenGL +import numpy + ## RenderPass used to display g-code paths. class LayerPass(RenderPass): def __init__(self, width, height): super().__init__("layerview", width, height) + self._controller = Application.getInstance().getController() + self._shader = None self._tool_handle_shader = None self._gl = OpenGL.getInstance().getBindingsObject() - self._scene = Application.getInstance().getController().getScene() + self._scene = self._controller.getScene() - self._layerview = None + self._layer_view = None + + self._controller.getScene().getRoot().childrenChanged.connect(self._onSceneChanged) + self._max_layers = 0 + self._current_layer_num = 0 + self._current_layer_mesh = None + self._current_layer_jumps = None + self._top_layers_job = None + self._activity = False + self._old_max_layers = 0 + + Preferences.getInstance().addPreference("view/top_layer_count", 5) + Preferences.getInstance().addPreference("view/only_show_top_layers", False) + Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged) + + self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) + self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) def setLayerView(self, layerview): - self._layerview = layerview + self._layer_view = layerview + + def getActivity(self): + return self._activity + + def getCurrentLayer(self): + return self._current_layer_num + + def getMaxLayers(self): + return self._max_layers + + def resetLayerData(self): + self._current_layer_mesh = None + self._current_layer_jumps = None + + def setLayer(self, value): + if self._current_layer_num != value: + self._current_layer_num = value + if self._current_layer_num < 0: + self._current_layer_num = 0 + if self._current_layer_num > self._max_layers: + self._current_layer_num = self._max_layers + + self._startUpdateTopLayers() + + self.currentLayerNumChanged.emit() + + def calculateMaxLayers(self): + scene = self._controller.getScene() + self._activity = True + + self._old_max_layers = self._max_layers + ## Recalculate num max layers + new_max_layers = 0 + for node in DepthFirstIterator(scene.getRoot()): + layer_data = node.callDecoration("getLayerData") + if not layer_data: + continue + + if new_max_layers < len(layer_data.getLayers()): + new_max_layers = len(layer_data.getLayers()) - 1 + + if new_max_layers > 0 and new_max_layers != self._old_max_layers: + self._max_layers = new_max_layers + + # The qt slider has a bit of weird behavior that if the maxvalue needs to be changed first + # if it's the largest value. If we don't do this, we can have a slider block outside of the + # slider. + if new_max_layers > self._current_layer_num: + self.maxLayersChanged.emit() + self.setLayer(int(self._max_layers)) + else: + self.setLayer(int(self._max_layers)) + self.maxLayersChanged.emit() + self._startUpdateTopLayers() + + maxLayersChanged = Signal() + currentLayerNumChanged = Signal() def render(self): if not self._shader: @@ -49,12 +131,12 @@ class LayerPass(RenderPass): continue # Render all layers below a certain number as line mesh instead of vertices. - if self._layerview._current_layer_num - self._layerview._solid_layers > -1 and not self._layerview._only_show_top_layers: + if self._current_layer_num - self._solid_layers > -1 and not self._only_show_top_layers: start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer, counts in element_counts.items(): - if layer + self._layerview._solid_layers > self._layerview._current_layer_num: + if layer + self._solid_layers > self._current_layer_num: break end += counts @@ -67,13 +149,13 @@ class LayerPass(RenderPass): batch = RenderBatch(self._shader, type = RenderBatch.RenderType.NoType, mode = RenderBatch.RenderMode.Lines) batch_has_items = False - if self._layerview._current_layer_mesh: + if self._current_layer_mesh: batch_has_items = True - batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_mesh) + batch.addItem(node.getWorldTransformation(), self._current_layer_mesh) - if self._layerview._current_layer_jumps: + if self._current_layer_jumps: batch_has_items = True - batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_jumps) + batch.addItem(node.getWorldTransformation(), self._current_layer_jumps) if batch_has_items: batch.render(self._scene.getActiveCamera()) @@ -84,3 +166,101 @@ class LayerPass(RenderPass): self._gl.glEnable(self._gl.GL_DEPTH_TEST) self.release() + + def _onSceneChanged(self, node): + self.calculateMaxLayers() + + def _startUpdateTopLayers(self): + if self._top_layers_job: + self._top_layers_job.finished.disconnect(self._updateCurrentLayerMesh) + self._top_layers_job.cancel() + + self._layer_view.setBusy(True) + + self._top_layers_job = _CreateTopLayersJob(self._controller.getScene(), self._current_layer_num, self._solid_layers) + self._top_layers_job.finished.connect(self._updateCurrentLayerMesh) + self._top_layers_job.start() + + def _updateCurrentLayerMesh(self, job): + self._layer_view.setBusy(False) + + if not job.getResult(): + return + self.resetLayerData() # Reset the layer data only when job is done. Doing it now prevents "blinking" data. + self._current_layer_mesh = job.getResult().get("layers") + self._current_layer_jumps = job.getResult().get("jumps") + self._controller.getScene().sceneChanged.emit(self._controller.getScene().getRoot()) + + self._top_layers_job = None + + def _onPreferencesChanged(self, preference): + if preference != "view/top_layer_count" and preference != "view/only_show_top_layers": + return + + self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) + self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) + + self._startUpdateTopLayers() + + +class _CreateTopLayersJob(Job): + def __init__(self, scene, layer_number, solid_layers): + super().__init__() + + self._scene = scene + self._layer_number = layer_number + self._solid_layers = solid_layers + self._cancel = False + + def run(self): + layer_data = None + for node in DepthFirstIterator(self._scene.getRoot()): + layer_data = node.callDecoration("getLayerData") + if layer_data: + break + + if self._cancel or not layer_data: + return + + layer_mesh = MeshBuilder() + for i in range(self._solid_layers): + layer_number = self._layer_number - i + if layer_number < 0: + continue + + try: + layer = layer_data.getLayer(layer_number).createMesh() + except Exception: + Logger.logException("w", "An exception occurred while creating layer mesh.") + return + + if not layer or layer.getVertices() is None: + continue + + layer_mesh.addIndices(layer_mesh.getVertexCount() + layer.getIndices()) + layer_mesh.addVertices(layer.getVertices()) + + # Scale layer color by a brightness factor based on the current layer number + # This will result in a range of 0.5 - 1.0 to multiply colors by. + brightness = numpy.ones((1, 4), dtype=numpy.float32) * (2.0 - (i / self._solid_layers)) / 2.0 + brightness[0, 3] = 1.0 + layer_mesh.addColors(layer.getColors() * brightness) + + if self._cancel: + return + + Job.yieldThread() + + if self._cancel: + return + + Job.yieldThread() + jump_mesh = layer_data.getLayer(self._layer_number).createJumps() + if not jump_mesh or jump_mesh.getVertices() is None: + jump_mesh = None + + self.setResult({"layers": layer_mesh.build(), "jumps": jump_mesh}) + + def cancel(self): + self._cancel = True + super().cancel() diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index e4c216ee85..550ffde9de 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -9,17 +9,12 @@ from UM.Event import Event, KeyEvent from UM.Signal import Signal from UM.Scene.Selection import Selection from UM.Math.Color import Color -from UM.Mesh.MeshBuilder import MeshBuilder -from UM.Job import Job -from UM.Preferences import Preferences -from UM.Logger import Logger from UM.Scene.SceneNode import SceneNode -from UM.View.RenderBatch import RenderBatch from UM.View.GL.OpenGL import OpenGL from cura.ConvexHullNode import ConvexHullNode -from PyQt5.QtCore import Qt, QTimer +from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication from . import LayerViewProxy @@ -29,7 +24,6 @@ catalog = i18nCatalog("cura") from . import LayerPass -import numpy import os.path ## View used to display g-code paths. @@ -37,14 +31,6 @@ class LayerView(View): def __init__(self): super().__init__() self._proxy = LayerViewProxy.LayerViewProxy() - self._controller.getScene().getRoot().childrenChanged.connect(self._onSceneChanged) - self._max_layers = 0 - self._current_layer_num = 0 - self._current_layer_mesh = None - self._current_layer_jumps = None - self._top_layers_job = None - self._activity = False - self._old_max_layers = 0 self._ghost_shader = None self._layer_pass = None @@ -53,25 +39,10 @@ class LayerView(View): self._layerview_composite_shader = None self._old_composite_shader = None - Preferences.getInstance().addPreference("view/top_layer_count", 5) - Preferences.getInstance().addPreference("view/only_show_top_layers", False) - Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged) - - self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) - self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) self._busy = False - def getActivity(self): - return self._activity - - def getCurrentLayer(self): - return self._current_layer_num - - def _onSceneChanged(self, node): - self.calculateMaxLayers() - - def getMaxLayers(self): - return self._max_layers + def getLayerPass(self): + return self._layer_pass busyChanged = Signal() @@ -83,10 +54,6 @@ class LayerView(View): self._busy = busy self.busyChanged.emit() - def resetLayerData(self): - self._current_layer_mesh = None - self._current_layer_jumps = None - def beginRendering(self): scene = self.getController().getScene() renderer = self.getRenderer() @@ -105,50 +72,6 @@ class LayerView(View): if node.getMeshData() and node.isVisible(): renderer.queueNode(node, transparent = True, shader = self._ghost_shader) - def setLayer(self, value): - if self._current_layer_num != value: - self._current_layer_num = value - if self._current_layer_num < 0: - self._current_layer_num = 0 - if self._current_layer_num > self._max_layers: - self._current_layer_num = self._max_layers - - self._startUpdateTopLayers() - - self.currentLayerNumChanged.emit() - - def calculateMaxLayers(self): - scene = self.getController().getScene() - self._activity = True - - self._old_max_layers = self._max_layers - ## Recalculate num max layers - new_max_layers = 0 - for node in DepthFirstIterator(scene.getRoot()): - layer_data = node.callDecoration("getLayerData") - if not layer_data: - continue - - if new_max_layers < len(layer_data.getLayers()): - new_max_layers = len(layer_data.getLayers()) - 1 - - if new_max_layers > 0 and new_max_layers != self._old_max_layers: - self._max_layers = new_max_layers - - # The qt slider has a bit of weird behavior that if the maxvalue needs to be changed first - # if it's the largest value. If we don't do this, we can have a slider block outside of the - # slider. - if new_max_layers > self._current_layer_num: - self.maxLayersChanged.emit() - self.setLayer(int(self._max_layers)) - else: - self.setLayer(int(self._max_layers)) - self.maxLayersChanged.emit() - self._startUpdateTopLayers() - - maxLayersChanged = Signal() - currentLayerNumChanged = Signal() - ## Hackish way to ensure the proxy is already created, which ensures that the layerview.qml is already created # as this caused some issues. def getProxy(self, engine, script_engine): @@ -162,10 +85,10 @@ class LayerView(View): ctrl_is_active = modifiers == Qt.ControlModifier if event.type == Event.KeyPressEvent and ctrl_is_active: if event.key == KeyEvent.UpKey: - self.setLayer(self._current_layer_num + 1) + self._layer_pass.setLayer(self._current_layer_num + 1) return True if event.key == KeyEvent.DownKey: - self.setLayer(self._current_layer_num - 1) + self._layer_pass.setLayer(self._current_layer_num - 1) return True if event.type == Event.ViewActivateEvent: @@ -192,98 +115,3 @@ class LayerView(View): if event.type == Event.ViewDeactivateEvent: self._composite_pass.setLayerBindings(self._old_layer_bindings) self._composite_pass.setCompositeShader(self._old_composite_shader) - - def _startUpdateTopLayers(self): - if self._top_layers_job: - self._top_layers_job.finished.disconnect(self._updateCurrentLayerMesh) - self._top_layers_job.cancel() - - self.setBusy(True) - - self._top_layers_job = _CreateTopLayersJob(self._controller.getScene(), self._current_layer_num, self._solid_layers) - self._top_layers_job.finished.connect(self._updateCurrentLayerMesh) - self._top_layers_job.start() - - def _updateCurrentLayerMesh(self, job): - self.setBusy(False) - - if not job.getResult(): - return - self.resetLayerData() # Reset the layer data only when job is done. Doing it now prevents "blinking" data. - self._current_layer_mesh = job.getResult().get("layers") - self._current_layer_jumps = job.getResult().get("jumps") - self._controller.getScene().sceneChanged.emit(self._controller.getScene().getRoot()) - - self._top_layers_job = None - - def _onPreferencesChanged(self, preference): - if preference != "view/top_layer_count" and preference != "view/only_show_top_layers": - return - - self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) - self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) - - self._startUpdateTopLayers() - - -class _CreateTopLayersJob(Job): - def __init__(self, scene, layer_number, solid_layers): - super().__init__() - - self._scene = scene - self._layer_number = layer_number - self._solid_layers = solid_layers - self._cancel = False - - def run(self): - layer_data = None - for node in DepthFirstIterator(self._scene.getRoot()): - layer_data = node.callDecoration("getLayerData") - if layer_data: - break - - if self._cancel or not layer_data: - return - - layer_mesh = MeshBuilder() - for i in range(self._solid_layers): - layer_number = self._layer_number - i - if layer_number < 0: - continue - - try: - layer = layer_data.getLayer(layer_number).createMesh() - except Exception: - Logger.logException("w", "An exception occurred while creating layer mesh.") - return - - if not layer or layer.getVertices() is None: - continue - - layer_mesh.addIndices(layer_mesh.getVertexCount() + layer.getIndices()) - layer_mesh.addVertices(layer.getVertices()) - - # Scale layer color by a brightness factor based on the current layer number - # This will result in a range of 0.5 - 1.0 to multiply colors by. - brightness = numpy.ones((1, 4), dtype=numpy.float32) * (2.0 - (i / self._solid_layers)) / 2.0 - brightness[0, 3] = 1.0 - layer_mesh.addColors(layer.getColors() * brightness) - - if self._cancel: - return - - Job.yieldThread() - - if self._cancel: - return - - Job.yieldThread() - jump_mesh = layer_data.getLayer(self._layer_number).createJumps() - if not jump_mesh or jump_mesh.getVertices() is None: - jump_mesh = None - - self.setResult({"layers": layer_mesh.build(), "jumps": jump_mesh}) - - def cancel(self): - self._cancel = True - super().cancel() diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py index bb9554ebf1..d770238393 100644 --- a/plugins/LayerView/LayerViewProxy.py +++ b/plugins/LayerView/LayerViewProxy.py @@ -19,20 +19,20 @@ class LayerViewProxy(QObject): def getLayerActivity(self): active_view = self._controller.getActiveView() if type(active_view) == LayerView.LayerView.LayerView: - return active_view.getActivity() + return active_view.getLayerPass().getActivity() @pyqtProperty(int, notify = maxLayersChanged) def numLayers(self): active_view = self._controller.getActiveView() if type(active_view) == LayerView.LayerView.LayerView: - return active_view.getMaxLayers() + return active_view.getLayerPass().getMaxLayers() #return 100 @pyqtProperty(int, notify = currentLayerChanged) def currentLayer(self): active_view = self._controller.getActiveView() if type(active_view) == LayerView.LayerView.LayerView: - return active_view.getCurrentLayer() + return active_view.getLayerPass().getCurrentLayer() busyChanged = pyqtSignal() @pyqtProperty(bool, notify = busyChanged) @@ -47,7 +47,7 @@ class LayerViewProxy(QObject): def setCurrentLayer(self, layer_num): active_view = self._controller.getActiveView() if type(active_view) == LayerView.LayerView.LayerView: - active_view.setLayer(layer_num) + active_view.getLayerPass().setLayer(layer_num) def _layerActivityChanged(self): self.activityChanged.emit() @@ -65,6 +65,6 @@ class LayerViewProxy(QObject): def _onActiveViewChanged(self): active_view = self._controller.getActiveView() if type(active_view) == LayerView.LayerView.LayerView: - active_view.currentLayerNumChanged.connect(self._onLayerChanged) - active_view.maxLayersChanged.connect(self._onMaxLayersChanged) + active_view.getLayerPass().currentLayerNumChanged.connect(self._onLayerChanged) + active_view.getLayerPass().maxLayersChanged.connect(self._onMaxLayersChanged) active_view.busyChanged.connect(self._onBusyChanged) From 66f8a62e6c1cf376ab6fb089a8d4911fc311e4b0 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Wed, 3 Aug 2016 15:20:26 +0200 Subject: [PATCH 05/11] Move busy handling into LayerPass and cleanup CURA-1601 --- plugins/LayerView/LayerPass.py | 19 +++++++++----- plugins/LayerView/LayerView.py | 39 +++++++++++------------------ plugins/LayerView/LayerViewProxy.py | 4 +-- 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index e14bab996a..5c310da603 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -30,8 +30,6 @@ class LayerPass(RenderPass): self._gl = OpenGL.getInstance().getBindingsObject() self._scene = self._controller.getScene() - self._layer_view = None - self._controller.getScene().getRoot().childrenChanged.connect(self._onSceneChanged) self._max_layers = 0 self._current_layer_num = 0 @@ -41,6 +39,8 @@ class LayerPass(RenderPass): self._activity = False self._old_max_layers = 0 + self._busy = False + Preferences.getInstance().addPreference("view/top_layer_count", 5) Preferences.getInstance().addPreference("view/only_show_top_layers", False) Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged) @@ -48,8 +48,15 @@ class LayerPass(RenderPass): self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) - def setLayerView(self, layerview): - self._layer_view = layerview + busyChanged = Signal() + + def isBusy(self): + return self._busy + + def setBusy(self, busy): + if busy != self._busy: + self._busy = busy + self.busyChanged.emit() def getActivity(self): return self._activity @@ -175,14 +182,14 @@ class LayerPass(RenderPass): self._top_layers_job.finished.disconnect(self._updateCurrentLayerMesh) self._top_layers_job.cancel() - self._layer_view.setBusy(True) + self.setBusy(True) self._top_layers_job = _CreateTopLayersJob(self._controller.getScene(), self._current_layer_num, self._solid_layers) self._top_layers_job.finished.connect(self._updateCurrentLayerMesh) self._top_layers_job.start() def _updateCurrentLayerMesh(self, job): - self._layer_view.setBusy(False) + self.setBusy(False) if not job.getResult(): return diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 550ffde9de..b06d37970b 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -6,7 +6,6 @@ from UM.View.View import View from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Resources import Resources from UM.Event import Event, KeyEvent -from UM.Signal import Signal from UM.Scene.Selection import Selection from UM.Math.Color import Color from UM.Scene.SceneNode import SceneNode @@ -39,20 +38,19 @@ class LayerView(View): self._layerview_composite_shader = None self._old_composite_shader = None - self._busy = False - def getLayerPass(self): + if not self._layer_pass: + # Currently the RenderPass constructor requires a size > 0 + # This should be fixed in RenderPass's constructor. + self._layer_pass = LayerPass.LayerPass(1, 1) + self.getRenderer().addRenderPass(self._layer_pass) + return self._layer_pass - busyChanged = Signal() - - def isBusy(self): - return self._busy - - def setBusy(self, busy): - if busy != self._busy: - self._busy = busy - self.busyChanged.emit() + ## Hackish way to ensure the proxy is already created, which ensures that the layerview.qml is already created + # as this caused some issues. + def getProxy(self, engine, script_engine): + return self._proxy def beginRendering(self): scene = self.getController().getScene() @@ -72,11 +70,6 @@ class LayerView(View): if node.getMeshData() and node.isVisible(): renderer.queueNode(node, transparent = True, shader = self._ghost_shader) - ## Hackish way to ensure the proxy is already created, which ensures that the layerview.qml is already created - # as this caused some issues. - def getProxy(self, engine, script_engine): - return self._proxy - def endRendering(self): pass @@ -85,19 +78,15 @@ class LayerView(View): ctrl_is_active = modifiers == Qt.ControlModifier if event.type == Event.KeyPressEvent and ctrl_is_active: if event.key == KeyEvent.UpKey: - self._layer_pass.setLayer(self._current_layer_num + 1) + self.getLayerPass().setLayer(self._current_layer_num + 1) return True if event.key == KeyEvent.DownKey: - self._layer_pass.setLayer(self._current_layer_num - 1) + self.getLayerPass().setLayer(self._current_layer_num - 1) return True if event.type == Event.ViewActivateEvent: - if not self._layer_pass: - # Currently the RenderPass constructor requires a size > 0 - # This should be fixed in RenderPass's constructor. - self._layer_pass = LayerPass.LayerPass(1, 1) - self._layer_pass.setLayerView(self) - self.getRenderer().addRenderPass(self._layer_pass) + # Make sure the LayerPass is created + self.getLayerPass() if not self._layerview_composite_shader: self._layerview_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("LayerView"), "layerview_composite.shader")) diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py index d770238393..32f1a27e4e 100644 --- a/plugins/LayerView/LayerViewProxy.py +++ b/plugins/LayerView/LayerViewProxy.py @@ -39,7 +39,7 @@ class LayerViewProxy(QObject): def busy(self): active_view = self._controller.getActiveView() if type(active_view) == LayerView.LayerView.LayerView: - return active_view.isBusy() + return active_view.getLayerPass().isBusy() return False @@ -67,4 +67,4 @@ class LayerViewProxy(QObject): if type(active_view) == LayerView.LayerView.LayerView: active_view.getLayerPass().currentLayerNumChanged.connect(self._onLayerChanged) active_view.getLayerPass().maxLayersChanged.connect(self._onMaxLayersChanged) - active_view.busyChanged.connect(self._onBusyChanged) + active_view.getLayerPass().busyChanged.connect(self._onBusyChanged) From 4e3f4162c2f5ca338ed2028acd74fe18b9ba34df Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 13 Aug 2016 13:02:43 +0200 Subject: [PATCH 06/11] Make background color a uniform CURA-1601 --- plugins/LayerView/layerview_composite.shader | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/LayerView/layerview_composite.shader b/plugins/LayerView/layerview_composite.shader index aad251f852..afa7f0ee39 100644 --- a/plugins/LayerView/layerview_composite.shader +++ b/plugins/LayerView/layerview_composite.shader @@ -23,6 +23,7 @@ fragment = uniform vec2 u_offset[9]; + uniform vec4 u_background_color; uniform float u_outline_strength; uniform vec4 u_outline_color; @@ -40,7 +41,7 @@ fragment = kernel[3] = 1.0; kernel[4] = -4.0; kernel[5] = 1.0; kernel[6] = 0.0; kernel[7] = 1.0; kernel[8] = 0.0; - vec4 result = vec4(0.965, 0.965, 0.965, 1.0); + vec4 result = u_background_color; vec4 layer0 = texture2D(u_layer0, v_uvs); vec4 layer2 = texture2D(u_layer2, v_uvs); @@ -70,6 +71,7 @@ u_layer0 = 0 u_layer1 = 1 u_layer2 = 2 u_layer3 = 3 +u_background_color = [0.965, 0.965, 0.965, 1.0] u_outline_strength = 1.0 u_outline_color = [0.05, 0.66, 0.89, 1.0] From f1b81dfad0bc4876d79ce1088f5d995b6f04c9eb Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 13 Aug 2016 13:03:49 +0200 Subject: [PATCH 07/11] Code style CURA-1601 --- plugins/LayerView/LayerView.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index b06d37970b..8622d75ee2 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -94,11 +94,9 @@ class LayerView(View): if not self._composite_pass: self._composite_pass = self.getRenderer().getRenderPass("composite") - self._old_layer_bindings = self._composite_pass.getLayerBindings() - layer_bindings = self._old_layer_bindings[:] # make a copy - layer_bindings.append("layerview") - self._composite_pass.setLayerBindings(layer_bindings) - self._old_composite_shader = self._composite_pass.getCompositeShader() + self._old_layer_bindings = self._composite_pass.getLayerBindings()[:] # make a copy so we can restore to it later + self._composite_pass.getLayerBindings().append("layerview") + self._old_composite_shader = self._composite_pass.getCompositeShader() self._composite_pass.setCompositeShader(self._layerview_composite_shader) if event.type == Event.ViewDeactivateEvent: From 5d9e1c2458cc20597e256f373f45515c3e9c6bcf Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 13 Aug 2016 13:05:11 +0200 Subject: [PATCH 08/11] Improve depth sorting on layers CURA-1601 --- plugins/LayerView/LayerPass.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index 5c310da603..b8dd279d41 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -30,7 +30,7 @@ class LayerPass(RenderPass): self._gl = OpenGL.getInstance().getBindingsObject() self._scene = self._controller.getScene() - self._controller.getScene().getRoot().childrenChanged.connect(self._onSceneChanged) + self._scene.getRoot().childrenChanged.connect(self._onSceneChanged) self._max_layers = 0 self._current_layer_num = 0 self._current_layer_mesh = None @@ -84,13 +84,12 @@ class LayerPass(RenderPass): self.currentLayerNumChanged.emit() def calculateMaxLayers(self): - scene = self._controller.getScene() self._activity = True self._old_max_layers = self._max_layers ## Recalculate num max layers new_max_layers = 0 - for node in DepthFirstIterator(scene.getRoot()): + for node in DepthFirstIterator(self._scene.getRoot()): layer_data = node.callDecoration("getLayerData") if not layer_data: continue @@ -122,7 +121,6 @@ class LayerPass(RenderPass): self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader")) self.bind() - self._gl.glDisable(self._gl.GL_DEPTH_TEST) tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay) tool_handle_has_items = False @@ -132,7 +130,7 @@ class LayerPass(RenderPass): tool_handle_batch.addItem(node.getWorldTransformation(), mesh = node.getSolidMesh()) tool_handle_has_items = True - if type(node) is SceneNode and node.getMeshData() and node.isVisible(): + elif isinstance(node, SceneNode) and node.getMeshData() and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: continue @@ -148,12 +146,12 @@ class LayerPass(RenderPass): end += counts # This uses glDrawRangeElements internally to only draw a certain range of lines. - batch = RenderBatch(self._shader, type = RenderBatch.RenderType.NoType, mode = RenderBatch.RenderMode.Lines, range = (start, end)) + batch = RenderBatch(self._shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (start, end)) batch.addItem(node.getWorldTransformation(), layer_data) batch.render(self._scene.getActiveCamera()) # Create a new batch that is not range-limited - batch = RenderBatch(self._shader, type = RenderBatch.RenderType.NoType, mode = RenderBatch.RenderMode.Lines) + batch = RenderBatch(self._shader, type = RenderBatch.RenderType.Solid) batch_has_items = False if self._current_layer_mesh: @@ -171,7 +169,6 @@ class LayerPass(RenderPass): if tool_handle_has_items: tool_handle_batch.render(self._scene.getActiveCamera()) - self._gl.glEnable(self._gl.GL_DEPTH_TEST) self.release() def _onSceneChanged(self, node): From 26a6df4c4d8dacc2a39604907b4ac625e88b1528 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 13 Aug 2016 13:49:45 +0200 Subject: [PATCH 09/11] Fix indentation CURA-1601 --- plugins/LayerView/LayerView.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 8622d75ee2..95fb95414a 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -96,7 +96,7 @@ class LayerView(View): self._old_layer_bindings = self._composite_pass.getLayerBindings()[:] # make a copy so we can restore to it later self._composite_pass.getLayerBindings().append("layerview") - self._old_composite_shader = self._composite_pass.getCompositeShader() + self._old_composite_shader = self._composite_pass.getCompositeShader() self._composite_pass.setCompositeShader(self._layerview_composite_shader) if event.type == Event.ViewDeactivateEvent: From 6c258e221474dd39b72ae8e5360dba6ca48b51c5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 12 Aug 2016 17:35:49 +0200 Subject: [PATCH 10/11] Update copyright notice Today we live in 2016. Contributes to issue CURA-1601. --- plugins/LayerView/LayerPass.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index b8dd279d41..10ddffe841 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015 Ultimaker B.V. +# Copyright (c) 2016 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. from UM.Logger import Logger From 0794f9f31c5f8b53dfa39fe941472d2a2a6d7269 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 12 Aug 2016 17:59:50 +0200 Subject: [PATCH 11/11] Fix grammar in documentation Contributes to issue CURA-1601. --- plugins/LayerView/LayerPass.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index 10ddffe841..289b38ccbd 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -100,7 +100,7 @@ class LayerPass(RenderPass): if new_max_layers > 0 and new_max_layers != self._old_max_layers: self._max_layers = new_max_layers - # The qt slider has a bit of weird behavior that if the maxvalue needs to be changed first + # The qt slider has a bit of weird behavior that the maxvalue needs to be changed first # if it's the largest value. If we don't do this, we can have a slider block outside of the # slider. if new_max_layers > self._current_layer_num: