mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 15:07:28 -06:00
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:
parent
243d51eb23
commit
b97015a354
5 changed files with 55 additions and 2 deletions
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue