Added 'align selected face with buildplate' feature.

Alt-click to select a face. See the (identically named) 'feature_bottom_face' branch in Uranium for more indepth information.
This commit is contained in:
Remco Burema 2019-09-02 00:17:14 +02:00
parent 243d51eb23
commit b97015a354
5 changed files with 55 additions and 2 deletions

View file

@ -7,11 +7,13 @@ from typing import List, cast
from UM.Event import CallFunctionEvent from UM.Event import CallFunctionEvent
from UM.FlameProfiler import pyqtSlot from UM.FlameProfiler import pyqtSlot
from UM.Math.Quaternion import Quaternion
from UM.Math.Vector import Vector from UM.Math.Vector import Vector
from UM.Scene.Selection import Selection from UM.Scene.Selection import Selection
from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator
from UM.Operations.GroupedOperation import GroupedOperation from UM.Operations.GroupedOperation import GroupedOperation
from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
from UM.Operations.RotateOperation import RotateOperation
from UM.Operations.TranslateOperation import TranslateOperation from UM.Operations.TranslateOperation import TranslateOperation
import cura.CuraApplication import cura.CuraApplication
@ -73,6 +75,36 @@ class CuraActions(QObject):
operation.addOperation(center_operation) operation.addOperation(center_operation)
operation.push() operation.push()
# Rotate the selection, so that the face that the mouse-pointer is on, faces the build-plate.
@pyqtSlot()
def bottomFaceSelection(self) -> None:
selected_face = Selection.getSelectedFace()
if not selected_face:
Logger.log("e", "Bottom face operation shouldn't have been called without a selected face.")
return
original_node, face_id = selected_face
meshdata = original_node.getMeshDataTransformed()
if not meshdata or face_id < 0 or face_id > 0x10001:
return
rotation_point, face_normal = meshdata.getFacePlane(face_id)
rotation_point_vector = Vector(rotation_point[0], rotation_point[1], rotation_point[2])
face_normal_vector = Vector(face_normal[0], face_normal[1], face_normal[2])
rotation_quaternion = Quaternion.rotationTo(face_normal_vector.normalized(), Vector(0.0, -1.0, 0.0))
operation = GroupedOperation()
for node in Selection.getAllSelectedObjects():
current_node = node
parent_node = current_node.getParent()
while parent_node and parent_node.callDecoration("isGroup"):
current_node = parent_node
parent_node = current_node.getParent()
rotate_operation = RotateOperation(current_node, rotation_quaternion, rotation_point_vector)
operation.addOperation(rotate_operation)
operation.push()
## Multiply all objects in the selection ## Multiply all objects in the selection
# #
# \param count The number of times to multiply the selection. # \param count The number of times to multiply the selection.

View file

@ -139,6 +139,10 @@ class SolidView(View):
shade_factor * int(material_color[5:7], 16) / 255, shade_factor * int(material_color[5:7], 16) / 255,
1.0 1.0
] ]
# Color the currently selected face-id, 0x10001 is certain to be greater than the largest ID.
face = Selection.getSelectedFace()
uniforms["selected_face"] = 0x10001 if not face or node != face[0] else face[1]
except ValueError: except ValueError:
pass pass

View file

@ -26,6 +26,7 @@ Item
property alias deleteSelection: deleteSelectionAction; property alias deleteSelection: deleteSelectionAction;
property alias centerSelection: centerSelectionAction; property alias centerSelection: centerSelectionAction;
property alias bottomFaceSelection: bottomFaceSelectionAction;
property alias multiplySelection: multiplySelectionAction; property alias multiplySelection: multiplySelectionAction;
property alias deleteObject: deleteObjectAction; property alias deleteObject: deleteObjectAction;
@ -271,6 +272,15 @@ Item
onTriggered: CuraActions.centerSelection(); onTriggered: CuraActions.centerSelection();
} }
Action
{
id: bottomFaceSelectionAction;
text: catalog.i18nc("@action:inmenu menubar:edit", "Align Selected Face To Bottom");
enabled: UM.Controller.toolsEnabled && UM.Selection.hasFaceSelected;
// iconName: "NO-ICON-YET"; // TODO?
onTriggered: CuraActions.bottomFaceSelection();
}
Action Action
{ {
id: multiplySelectionAction; id: multiplySelectionAction;

View file

@ -20,6 +20,7 @@ Menu
// Selection-related actions. // Selection-related actions.
MenuItem { action: Cura.Actions.centerSelection; } MenuItem { action: Cura.Actions.centerSelection; }
MenuItem { action: Cura.Actions.deleteSelection; } MenuItem { action: Cura.Actions.deleteSelection; }
MenuItem { action: Cura.Actions.bottomFaceSelection; }
MenuItem { action: Cura.Actions.multiplySelection; } MenuItem { action: Cura.Actions.multiplySelection; }
// Extruder selection - only visible if there is more than 1 extruder // Extruder selection - only visible if there is more than 1 extruder

View file

@ -32,6 +32,8 @@ fragment =
uniform lowp float u_overhangAngle; uniform lowp float u_overhangAngle;
uniform lowp vec4 u_overhangColor; uniform lowp vec4 u_overhangColor;
uniform lowp vec4 u_faceColor;
uniform highp int u_faceId;
varying highp vec3 f_vertex; varying highp vec3 f_vertex;
varying highp vec3 f_normal; varying highp vec3 f_normal;
@ -58,7 +60,7 @@ fragment =
highp float NdotR = clamp(dot(viewVector, reflectedLight), 0.0, 1.0); highp float NdotR = clamp(dot(viewVector, reflectedLight), 0.0, 1.0);
finalColor += pow(NdotR, u_shininess) * u_specularColor; finalColor += pow(NdotR, u_shininess) * u_specularColor;
finalColor = (-normal.y > u_overhangAngle) ? u_overhangColor : finalColor; finalColor = (u_faceId != gl_PrimitiveID) ? ((-normal.y > u_overhangAngle) ? u_overhangColor : finalColor) : u_faceColor;
gl_FragColor = finalColor; gl_FragColor = finalColor;
gl_FragColor.a = 1.0; gl_FragColor.a = 1.0;
@ -99,6 +101,8 @@ fragment41core =
uniform lowp float u_overhangAngle; uniform lowp float u_overhangAngle;
uniform lowp vec4 u_overhangColor; uniform lowp vec4 u_overhangColor;
uniform lowp vec4 u_faceColor;
uniform highp int u_faceId;
in highp vec3 f_vertex; in highp vec3 f_vertex;
in highp vec3 f_normal; in highp vec3 f_normal;
@ -127,7 +131,7 @@ fragment41core =
highp float NdotR = clamp(dot(viewVector, reflectedLight), 0.0, 1.0); highp float NdotR = clamp(dot(viewVector, reflectedLight), 0.0, 1.0);
finalColor += pow(NdotR, u_shininess) * u_specularColor; finalColor += pow(NdotR, u_shininess) * u_specularColor;
finalColor = (-normal.y > u_overhangAngle) ? u_overhangColor : finalColor; finalColor = (u_faceId != gl_PrimitiveID) ? ((-normal.y > u_overhangAngle) ? u_overhangColor : finalColor) : u_faceColor;
frag_color = finalColor; frag_color = finalColor;
frag_color.a = 1.0; frag_color.a = 1.0;
@ -138,6 +142,7 @@ u_ambientColor = [0.3, 0.3, 0.3, 1.0]
u_diffuseColor = [1.0, 0.79, 0.14, 1.0] u_diffuseColor = [1.0, 0.79, 0.14, 1.0]
u_specularColor = [0.4, 0.4, 0.4, 1.0] u_specularColor = [0.4, 0.4, 0.4, 1.0]
u_overhangColor = [1.0, 0.0, 0.0, 1.0] u_overhangColor = [1.0, 0.0, 0.0, 1.0]
u_faceColor = [0.0, 0.0, 1.0, 1.0]
u_shininess = 20.0 u_shininess = 20.0
[bindings] [bindings]
@ -148,6 +153,7 @@ u_normalMatrix = normal_matrix
u_viewPosition = view_position u_viewPosition = view_position
u_lightPosition = light_0_position u_lightPosition = light_0_position
u_diffuseColor = diffuse_color u_diffuseColor = diffuse_color
u_faceId = selected_face
[attributes] [attributes]
a_vertex = vertex a_vertex = vertex