mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 02:35:54 +08:00
Merge branch 'master' of https://github.com/Prusa-Development/PrusaSlicerPrivate into et_transformations
This commit is contained in:
commit
4944b66928
@ -24,6 +24,9 @@ struct SlopeDetection
|
|||||||
};
|
};
|
||||||
|
|
||||||
uniform vec4 uniform_color;
|
uniform vec4 uniform_color;
|
||||||
|
uniform bool use_color_clip_plane;
|
||||||
|
uniform vec4 uniform_color_clip_plane_1;
|
||||||
|
uniform vec4 uniform_color_clip_plane_2;
|
||||||
uniform SlopeDetection slope;
|
uniform SlopeDetection slope;
|
||||||
|
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
@ -34,6 +37,7 @@ uniform SlopeDetection slope;
|
|||||||
uniform PrintVolumeDetection print_volume;
|
uniform PrintVolumeDetection print_volume;
|
||||||
|
|
||||||
varying vec3 clipping_planes_dots;
|
varying vec3 clipping_planes_dots;
|
||||||
|
varying float color_clip_plane_dot;
|
||||||
|
|
||||||
// x = diffuse, y = specular;
|
// x = diffuse, y = specular;
|
||||||
varying vec2 intensity;
|
varying vec2 intensity;
|
||||||
@ -46,12 +50,18 @@ void main()
|
|||||||
{
|
{
|
||||||
if (any(lessThan(clipping_planes_dots, ZERO)))
|
if (any(lessThan(clipping_planes_dots, ZERO)))
|
||||||
discard;
|
discard;
|
||||||
vec3 color = uniform_color.rgb;
|
|
||||||
float alpha = uniform_color.a;
|
vec4 color;
|
||||||
|
if (use_color_clip_plane) {
|
||||||
|
color.rgb = (color_clip_plane_dot < 0.0) ? uniform_color_clip_plane_1.rgb : uniform_color_clip_plane_2.rgb;
|
||||||
|
color.a = uniform_color.a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
color = uniform_color;
|
||||||
|
|
||||||
if (slope.actived && world_normal_z < slope.normal_z - EPSILON) {
|
if (slope.actived && world_normal_z < slope.normal_z - EPSILON) {
|
||||||
color = vec3(0.7, 0.7, 1.0);
|
color.rgb = vec3(0.7, 0.7, 1.0);
|
||||||
alpha = 1.0;
|
color.a = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the fragment is outside the print volume -> use darker color
|
// if the fragment is outside the print volume -> use darker color
|
||||||
@ -68,12 +78,12 @@ void main()
|
|||||||
pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x);
|
pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x);
|
||||||
pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
|
pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
|
||||||
}
|
}
|
||||||
color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color;
|
color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb;
|
||||||
|
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
if (use_environment_tex)
|
if (use_environment_tex)
|
||||||
gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha);
|
gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha);
|
gl_FragColor = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ uniform SlopeDetection slope;
|
|||||||
uniform vec2 z_range;
|
uniform vec2 z_range;
|
||||||
// Clipping plane - general orientation. Used by the SLA gizmo.
|
// Clipping plane - general orientation. Used by the SLA gizmo.
|
||||||
uniform vec4 clipping_plane;
|
uniform vec4 clipping_plane;
|
||||||
|
// Color clip plane - general orientation. Used by the cut gizmo.
|
||||||
|
uniform vec4 color_clip_plane;
|
||||||
|
|
||||||
attribute vec3 v_position;
|
attribute vec3 v_position;
|
||||||
attribute vec3 v_normal;
|
attribute vec3 v_normal;
|
||||||
@ -43,6 +45,7 @@ attribute vec3 v_normal;
|
|||||||
varying vec2 intensity;
|
varying vec2 intensity;
|
||||||
|
|
||||||
varying vec3 clipping_planes_dots;
|
varying vec3 clipping_planes_dots;
|
||||||
|
varying float color_clip_plane_dot;
|
||||||
|
|
||||||
varying vec4 world_pos;
|
varying vec4 world_pos;
|
||||||
varying float world_normal_z;
|
varying float world_normal_z;
|
||||||
@ -74,4 +77,5 @@ void main()
|
|||||||
gl_Position = projection_matrix * position;
|
gl_Position = projection_matrix * position;
|
||||||
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
|
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
|
||||||
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
|
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
|
||||||
|
color_clip_plane_dot = dot(world_pos, color_clip_plane);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,9 @@ struct SlopeDetection
|
|||||||
};
|
};
|
||||||
|
|
||||||
uniform vec4 uniform_color;
|
uniform vec4 uniform_color;
|
||||||
|
uniform bool use_color_clip_plane;
|
||||||
|
uniform vec4 uniform_color_clip_plane_1;
|
||||||
|
uniform vec4 uniform_color_clip_plane_2;
|
||||||
uniform SlopeDetection slope;
|
uniform SlopeDetection slope;
|
||||||
|
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
@ -34,6 +37,7 @@ uniform SlopeDetection slope;
|
|||||||
uniform PrintVolumeDetection print_volume;
|
uniform PrintVolumeDetection print_volume;
|
||||||
|
|
||||||
in vec3 clipping_planes_dots;
|
in vec3 clipping_planes_dots;
|
||||||
|
in float color_clip_plane_dot;
|
||||||
|
|
||||||
// x = diffuse, y = specular;
|
// x = diffuse, y = specular;
|
||||||
in vec2 intensity;
|
in vec2 intensity;
|
||||||
@ -48,12 +52,18 @@ void main()
|
|||||||
{
|
{
|
||||||
if (any(lessThan(clipping_planes_dots, ZERO)))
|
if (any(lessThan(clipping_planes_dots, ZERO)))
|
||||||
discard;
|
discard;
|
||||||
vec3 color = uniform_color.rgb;
|
|
||||||
float alpha = uniform_color.a;
|
vec4 color;
|
||||||
|
if (use_color_clip_plane) {
|
||||||
|
color.rgb = (color_clip_plane_dot < 0.0) ? uniform_color_clip_plane_1.rgb : uniform_color_clip_plane_2.rgb;
|
||||||
|
color.a = uniform_color.a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
color = uniform_color;
|
||||||
|
|
||||||
if (slope.actived && world_normal_z < slope.normal_z - EPSILON) {
|
if (slope.actived && world_normal_z < slope.normal_z - EPSILON) {
|
||||||
color = vec3(0.7, 0.7, 1.0);
|
color.rgb = vec3(0.7, 0.7, 1.0);
|
||||||
alpha = 1.0;
|
color.a = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the fragment is outside the print volume -> use darker color
|
// if the fragment is outside the print volume -> use darker color
|
||||||
@ -70,12 +80,12 @@ void main()
|
|||||||
pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x);
|
pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x);
|
||||||
pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
|
pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
|
||||||
}
|
}
|
||||||
color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color;
|
color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb;
|
||||||
|
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
if (use_environment_tex)
|
if (use_environment_tex)
|
||||||
out_color = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha);
|
out_color = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
out_color = vec4(vec3(intensity.y) + color * intensity.x, alpha);
|
out_color = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ uniform SlopeDetection slope;
|
|||||||
uniform vec2 z_range;
|
uniform vec2 z_range;
|
||||||
// Clipping plane - general orientation. Used by the SLA gizmo.
|
// Clipping plane - general orientation. Used by the SLA gizmo.
|
||||||
uniform vec4 clipping_plane;
|
uniform vec4 clipping_plane;
|
||||||
|
// Color clip plane - general orientation. Used by the cut gizmo.
|
||||||
|
uniform vec4 color_clip_plane;
|
||||||
|
|
||||||
in vec3 v_position;
|
in vec3 v_position;
|
||||||
in vec3 v_normal;
|
in vec3 v_normal;
|
||||||
@ -43,6 +45,7 @@ in vec3 v_normal;
|
|||||||
out vec2 intensity;
|
out vec2 intensity;
|
||||||
|
|
||||||
out vec3 clipping_planes_dots;
|
out vec3 clipping_planes_dots;
|
||||||
|
out float color_clip_plane_dot;
|
||||||
|
|
||||||
out vec4 world_pos;
|
out vec4 world_pos;
|
||||||
out float world_normal_z;
|
out float world_normal_z;
|
||||||
@ -74,4 +77,5 @@ void main()
|
|||||||
gl_Position = projection_matrix * position;
|
gl_Position = projection_matrix * position;
|
||||||
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
|
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
|
||||||
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
|
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
|
||||||
|
color_clip_plane_dot = dot(world_pos, color_clip_plane);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,9 @@ struct SlopeDetection
|
|||||||
};
|
};
|
||||||
|
|
||||||
uniform vec4 uniform_color;
|
uniform vec4 uniform_color;
|
||||||
|
uniform bool use_color_clip_plane;
|
||||||
|
uniform vec4 uniform_color_clip_plane_1;
|
||||||
|
uniform vec4 uniform_color_clip_plane_2;
|
||||||
uniform SlopeDetection slope;
|
uniform SlopeDetection slope;
|
||||||
|
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
@ -36,6 +39,7 @@ uniform SlopeDetection slope;
|
|||||||
uniform PrintVolumeDetection print_volume;
|
uniform PrintVolumeDetection print_volume;
|
||||||
|
|
||||||
varying vec3 clipping_planes_dots;
|
varying vec3 clipping_planes_dots;
|
||||||
|
varying float color_clip_plane_dot;
|
||||||
|
|
||||||
// x = diffuse, y = specular;
|
// x = diffuse, y = specular;
|
||||||
varying vec2 intensity;
|
varying vec2 intensity;
|
||||||
@ -48,12 +52,18 @@ void main()
|
|||||||
{
|
{
|
||||||
if (any(lessThan(clipping_planes_dots, ZERO)))
|
if (any(lessThan(clipping_planes_dots, ZERO)))
|
||||||
discard;
|
discard;
|
||||||
vec3 color = uniform_color.rgb;
|
|
||||||
float alpha = uniform_color.a;
|
vec4 color;
|
||||||
|
if (use_color_clip_plane) {
|
||||||
|
color.rgb = (color_clip_plane_dot < 0.0) ? uniform_color_clip_plane_1.rgb : uniform_color_clip_plane_2.rgb;
|
||||||
|
color.a = uniform_color.a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
color = uniform_color;
|
||||||
|
|
||||||
if (slope.actived && world_normal_z < slope.normal_z - EPSILON) {
|
if (slope.actived && world_normal_z < slope.normal_z - EPSILON) {
|
||||||
color = vec3(0.7, 0.7, 1.0);
|
color.rgb = vec3(0.7, 0.7, 1.0);
|
||||||
alpha = 1.0;
|
color.a = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the fragment is outside the print volume -> use darker color
|
// if the fragment is outside the print volume -> use darker color
|
||||||
@ -70,12 +80,12 @@ void main()
|
|||||||
pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x);
|
pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x);
|
||||||
pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
|
pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
|
||||||
}
|
}
|
||||||
color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color;
|
color.rgb = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color.rgb, ZERO, 0.3333) : color.rgb;
|
||||||
|
|
||||||
#ifdef ENABLE_ENVIRONMENT_MAP
|
#ifdef ENABLE_ENVIRONMENT_MAP
|
||||||
if (use_environment_tex)
|
if (use_environment_tex)
|
||||||
gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha);
|
gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color.rgb * intensity.x, color.a);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha);
|
gl_FragColor = vec4(vec3(intensity.y) + color.rgb * intensity.x, color.a);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ uniform SlopeDetection slope;
|
|||||||
uniform vec2 z_range;
|
uniform vec2 z_range;
|
||||||
// Clipping plane - general orientation. Used by the SLA gizmo.
|
// Clipping plane - general orientation. Used by the SLA gizmo.
|
||||||
uniform vec4 clipping_plane;
|
uniform vec4 clipping_plane;
|
||||||
|
// Color clip plane - general orientation. Used by the cut gizmo.
|
||||||
|
uniform vec4 color_clip_plane;
|
||||||
|
|
||||||
attribute vec3 v_position;
|
attribute vec3 v_position;
|
||||||
attribute vec3 v_normal;
|
attribute vec3 v_normal;
|
||||||
@ -43,6 +45,7 @@ attribute vec3 v_normal;
|
|||||||
varying vec2 intensity;
|
varying vec2 intensity;
|
||||||
|
|
||||||
varying vec3 clipping_planes_dots;
|
varying vec3 clipping_planes_dots;
|
||||||
|
varying float color_clip_plane_dot;
|
||||||
|
|
||||||
varying vec4 world_pos;
|
varying vec4 world_pos;
|
||||||
varying float world_normal_z;
|
varying float world_normal_z;
|
||||||
@ -74,4 +77,5 @@ void main()
|
|||||||
gl_Position = projection_matrix * position;
|
gl_Position = projection_matrix * position;
|
||||||
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
|
// Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
|
||||||
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
|
clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
|
||||||
|
color_clip_plane_dot = dot(world_pos, color_clip_plane);
|
||||||
}
|
}
|
||||||
|
@ -1305,7 +1305,9 @@ void ModelObject::synchronize_model_after_cut()
|
|||||||
void ModelObject::apply_cut_attributes(ModelObjectCutAttributes attributes)
|
void ModelObject::apply_cut_attributes(ModelObjectCutAttributes attributes)
|
||||||
{
|
{
|
||||||
// we don't save cut information, if result will not contains all parts of initial object
|
// we don't save cut information, if result will not contains all parts of initial object
|
||||||
if (!attributes.has(ModelObjectCutAttribute::KeepUpper) || !attributes.has(ModelObjectCutAttribute::KeepLower))
|
if (!attributes.has(ModelObjectCutAttribute::KeepUpper) ||
|
||||||
|
!attributes.has(ModelObjectCutAttribute::KeepLower) ||
|
||||||
|
attributes.has(ModelObjectCutAttribute::InvalidateCutInfo))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cut_id.id().invalid())
|
if (cut_id.id().invalid())
|
||||||
@ -1425,7 +1427,7 @@ void ModelObject::process_modifier_cut(ModelVolume* volume, const Transform3d& i
|
|||||||
lower->add_volume(*volume);
|
lower->add_volume(*volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_cut_volume(TriangleMesh& mesh, ModelObject* object, const ModelVolume* src_volume, const Transform3d& cut_matrix)
|
static void add_cut_volume(TriangleMesh& mesh, ModelObject* object, const ModelVolume* src_volume, const Transform3d& cut_matrix, const std::string& suffix = {})
|
||||||
{
|
{
|
||||||
if (mesh.empty())
|
if (mesh.empty())
|
||||||
return;
|
return;
|
||||||
@ -1433,7 +1435,7 @@ static void add_cut_volume(TriangleMesh& mesh, ModelObject* object, const ModelV
|
|||||||
mesh.transform(cut_matrix);
|
mesh.transform(cut_matrix);
|
||||||
ModelVolume* vol = object->add_volume(mesh);
|
ModelVolume* vol = object->add_volume(mesh);
|
||||||
|
|
||||||
vol->name = src_volume->name;
|
vol->name = src_volume->name + suffix;
|
||||||
// Don't copy the config's ID.
|
// Don't copy the config's ID.
|
||||||
vol->config.assign_config(src_volume->config);
|
vol->config.assign_config(src_volume->config);
|
||||||
assert(vol->config.id().valid());
|
assert(vol->config.id().valid());
|
||||||
@ -1477,6 +1479,12 @@ void ModelObject::process_solid_part_cut(ModelVolume* volume, const Transform3d&
|
|||||||
|
|
||||||
// Add required cut parts to the objects
|
// Add required cut parts to the objects
|
||||||
|
|
||||||
|
if (attributes.has(ModelObjectCutAttribute::KeepAsParts)) {
|
||||||
|
add_cut_volume(upper_mesh, upper, volume, cut_matrix, "_A");
|
||||||
|
add_cut_volume(lower_mesh, upper, volume, cut_matrix, "_B");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper))
|
if (attributes.has(ModelObjectCutAttribute::KeepUpper))
|
||||||
add_cut_volume(upper_mesh, upper, volume, cut_matrix);
|
add_cut_volume(upper_mesh, upper, volume, cut_matrix);
|
||||||
|
|
||||||
@ -1560,7 +1568,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Transform3d& cut_matrix,
|
|||||||
clone_for_cut(&upper);
|
clone_for_cut(&upper);
|
||||||
|
|
||||||
ModelObject* lower{ nullptr };
|
ModelObject* lower{ nullptr };
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepLower))
|
if (attributes.has(ModelObjectCutAttribute::KeepLower) && !attributes.has(ModelObjectCutAttribute::KeepAsParts))
|
||||||
clone_for_cut(&lower);
|
clone_for_cut(&lower);
|
||||||
|
|
||||||
std::vector<ModelObject*> dowels;
|
std::vector<ModelObject*> dowels;
|
||||||
@ -1608,34 +1616,40 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Transform3d& cut_matrix,
|
|||||||
|
|
||||||
ModelObjectPtrs res;
|
ModelObjectPtrs res;
|
||||||
|
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper) && !upper->volumes.empty()) {
|
if (attributes.has(ModelObjectCutAttribute::KeepAsParts) && !upper->volumes.empty()) {
|
||||||
invalidate_translations(upper, instances[instance]);
|
reset_instance_transformation(upper, instance, cut_matrix);
|
||||||
|
|
||||||
reset_instance_transformation(upper, instance, cut_matrix,
|
|
||||||
attributes.has(ModelObjectCutAttribute::PlaceOnCutUpper),
|
|
||||||
attributes.has(ModelObjectCutAttribute::FlipUpper),
|
|
||||||
local_displace);
|
|
||||||
res.push_back(upper);
|
res.push_back(upper);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (attributes.has(ModelObjectCutAttribute::KeepUpper) && !upper->volumes.empty()) {
|
||||||
|
invalidate_translations(upper, instances[instance]);
|
||||||
|
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepLower) && !lower->volumes.empty()) {
|
reset_instance_transformation(upper, instance, cut_matrix,
|
||||||
invalidate_translations(lower, instances[instance]);
|
attributes.has(ModelObjectCutAttribute::PlaceOnCutUpper),
|
||||||
|
attributes.has(ModelObjectCutAttribute::FlipUpper),
|
||||||
|
local_displace);
|
||||||
|
res.push_back(upper);
|
||||||
|
}
|
||||||
|
|
||||||
reset_instance_transformation(lower, instance, cut_matrix,
|
if (attributes.has(ModelObjectCutAttribute::KeepLower) && !lower->volumes.empty()) {
|
||||||
attributes.has(ModelObjectCutAttribute::PlaceOnCutLower),
|
invalidate_translations(lower, instances[instance]);
|
||||||
attributes.has(ModelObjectCutAttribute::PlaceOnCutLower) ? true : attributes.has(ModelObjectCutAttribute::FlipLower));
|
|
||||||
res.push_back(lower);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributes.has(ModelObjectCutAttribute::CreateDowels) && !dowels.empty()) {
|
reset_instance_transformation(lower, instance, cut_matrix,
|
||||||
for (auto dowel : dowels) {
|
attributes.has(ModelObjectCutAttribute::PlaceOnCutLower),
|
||||||
invalidate_translations(dowel, instances[instance]);
|
attributes.has(ModelObjectCutAttribute::PlaceOnCutLower) ? true : attributes.has(ModelObjectCutAttribute::FlipLower));
|
||||||
|
res.push_back(lower);
|
||||||
|
}
|
||||||
|
|
||||||
reset_instance_transformation(dowel, instance, Transform3d::Identity(), false, false, local_dowels_displace);
|
if (attributes.has(ModelObjectCutAttribute::CreateDowels) && !dowels.empty()) {
|
||||||
|
for (auto dowel : dowels) {
|
||||||
|
invalidate_translations(dowel, instances[instance]);
|
||||||
|
|
||||||
local_dowels_displace += dowel->full_raw_mesh_bounding_box().size().cwiseProduct(Vec3d(-1.5, -1.5, 0.0));
|
reset_instance_transformation(dowel, instance, Transform3d::Identity(), false, false, local_dowels_displace);
|
||||||
dowel->name += "-Dowel-" + dowel->volumes[0]->name;
|
|
||||||
res.push_back(dowel);
|
local_dowels_displace += dowel->full_raw_mesh_bounding_box().size().cwiseProduct(Vec3d(-1.5, -1.5, 0.0));
|
||||||
|
dowel->name += "-Dowel-" + dowel->volumes[0]->name;
|
||||||
|
res.push_back(dowel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ enum class ModelVolumeType : int {
|
|||||||
SUPPORT_ENFORCER,
|
SUPPORT_ENFORCER,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipUpper, FlipLower, PlaceOnCutUpper, PlaceOnCutLower, CreateDowels };
|
enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, KeepAsParts, FlipUpper, FlipLower, PlaceOnCutUpper, PlaceOnCutLower, CreateDowels, InvalidateCutInfo };
|
||||||
using ModelObjectCutAttributes = enum_bitmask<ModelObjectCutAttribute>;
|
using ModelObjectCutAttributes = enum_bitmask<ModelObjectCutAttribute>;
|
||||||
ENABLE_ENUM_BITMASK_OPERATORS(ModelObjectCutAttribute);
|
ENABLE_ENUM_BITMASK_OPERATORS(ModelObjectCutAttribute);
|
||||||
|
|
||||||
|
@ -814,6 +814,10 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
|
|||||||
|
|
||||||
shader->set_uniform("z_range", m_z_range);
|
shader->set_uniform("z_range", m_z_range);
|
||||||
shader->set_uniform("clipping_plane", m_clipping_plane);
|
shader->set_uniform("clipping_plane", m_clipping_plane);
|
||||||
|
shader->set_uniform("use_color_clip_plane", m_use_color_clip_plane);
|
||||||
|
shader->set_uniform("color_clip_plane", m_color_clip_plane);
|
||||||
|
shader->set_uniform("uniform_color_clip_plane_1", m_color_clip_plane_colors[0]);
|
||||||
|
shader->set_uniform("uniform_color_clip_plane_2", m_color_clip_plane_colors[1]);
|
||||||
shader->set_uniform("print_volume.type", static_cast<int>(m_print_volume.type));
|
shader->set_uniform("print_volume.type", static_cast<int>(m_print_volume.type));
|
||||||
shader->set_uniform("print_volume.xy_data", m_print_volume.data);
|
shader->set_uniform("print_volume.xy_data", m_print_volume.data);
|
||||||
shader->set_uniform("print_volume.z_data", m_print_volume.zs);
|
shader->set_uniform("print_volume.z_data", m_print_volume.zs);
|
||||||
|
@ -387,6 +387,12 @@ private:
|
|||||||
// plane coeffs for clipping in shaders
|
// plane coeffs for clipping in shaders
|
||||||
std::array<double, 4> m_clipping_plane;
|
std::array<double, 4> m_clipping_plane;
|
||||||
|
|
||||||
|
// plane coeffs for render volumes with different colors in shaders
|
||||||
|
// used by cut gizmo
|
||||||
|
std::array<double, 4> m_color_clip_plane;
|
||||||
|
bool m_use_color_clip_plane{ false };
|
||||||
|
std::array<ColorRGBA, 2> m_color_clip_plane_colors{ ColorRGBA::RED(), ColorRGBA::BLUE() };
|
||||||
|
|
||||||
struct Slope
|
struct Slope
|
||||||
{
|
{
|
||||||
// toggle for slope rendering
|
// toggle for slope rendering
|
||||||
@ -445,6 +451,14 @@ public:
|
|||||||
const std::array<float, 2>& get_z_range() const { return m_z_range; }
|
const std::array<float, 2>& get_z_range() const { return m_z_range; }
|
||||||
const std::array<double, 4>& get_clipping_plane() const { return m_clipping_plane; }
|
const std::array<double, 4>& get_clipping_plane() const { return m_clipping_plane; }
|
||||||
|
|
||||||
|
void set_use_color_clip_plane(bool use) { m_use_color_clip_plane = use; }
|
||||||
|
void set_color_clip_plane(const Vec3d& cp_normal, double offset) {
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
m_color_clip_plane[i] = -cp_normal[i];
|
||||||
|
m_color_clip_plane[3] = offset;
|
||||||
|
}
|
||||||
|
void set_color_clip_plane_colors(const std::array<ColorRGBA, 2>& colors) { m_color_clip_plane_colors = colors; }
|
||||||
|
|
||||||
bool is_slope_active() const { return m_slope.active; }
|
bool is_slope_active() const { return m_slope.active; }
|
||||||
void set_slope_active(bool active) { m_slope.active = active; }
|
void set_slope_active(bool active) { m_slope.active = active; }
|
||||||
|
|
||||||
|
@ -712,6 +712,10 @@ public:
|
|||||||
bool get_use_clipping_planes() const { return m_use_clipping_planes; }
|
bool get_use_clipping_planes() const { return m_use_clipping_planes; }
|
||||||
const std::array<ClippingPlane, 2> &get_clipping_planes() const { return m_clipping_planes; };
|
const std::array<ClippingPlane, 2> &get_clipping_planes() const { return m_clipping_planes; };
|
||||||
|
|
||||||
|
void set_use_color_clip_plane(bool use) { m_volumes.set_use_color_clip_plane(use); }
|
||||||
|
void set_color_clip_plane(const Vec3d& cp_normal, double offset) { m_volumes.set_color_clip_plane(cp_normal, offset); }
|
||||||
|
void set_color_clip_plane_colors(const std::array<ColorRGBA, 2>& colors) { m_volumes.set_color_clip_plane_colors(colors); }
|
||||||
|
|
||||||
void refresh_camera_scene_box();
|
void refresh_camera_scene_box();
|
||||||
|
|
||||||
BoundingBoxf3 volumes_bounding_box() const;
|
BoundingBoxf3 volumes_bounding_box() const;
|
||||||
|
@ -21,6 +21,8 @@ namespace Slic3r {
|
|||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
static const ColorRGBA GRABBER_COLOR = ColorRGBA::YELLOW();
|
static const ColorRGBA GRABBER_COLOR = ColorRGBA::YELLOW();
|
||||||
|
static const ColorRGBA UPPER_PART_COLOR = ColorRGBA::CYAN();
|
||||||
|
static const ColorRGBA LOWER_PART_COLOR = ColorRGBA::MAGENTA();
|
||||||
|
|
||||||
// connector colors
|
// connector colors
|
||||||
static const ColorRGBA PLAG_COLOR = ColorRGBA::YELLOW();
|
static const ColorRGBA PLAG_COLOR = ColorRGBA::YELLOW();
|
||||||
@ -196,7 +198,7 @@ static void init_from_angle_arc(GLModel& model, double angle, double radius)
|
|||||||
|
|
||||||
GLGizmoCut3D::GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
GLGizmoCut3D::GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
, m_connectors_group_id (3)
|
, m_connectors_group_id (GrabberID::Count)
|
||||||
, m_connector_type (CutConnectorType::Plug)
|
, m_connector_type (CutConnectorType::Plug)
|
||||||
, m_connector_style (size_t(CutConnectorStyle::Prizm))
|
, m_connector_style (size_t(CutConnectorStyle::Prizm))
|
||||||
, m_connector_shape_id (size_t(CutConnectorShape::Circle))
|
, m_connector_shape_id (size_t(CutConnectorShape::Circle))
|
||||||
@ -227,13 +229,19 @@ GLGizmoCut3D::GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename,
|
|||||||
|
|
||||||
m_axis_names = { "X", "Y", "Z" };
|
m_axis_names = { "X", "Y", "Z" };
|
||||||
|
|
||||||
|
m_part_orientation_names = {
|
||||||
|
{"none", _L("Keep orientation")},
|
||||||
|
{"on_cut", _L("Place on cut")},
|
||||||
|
{"flip", _L("Flip upside down")},
|
||||||
|
};
|
||||||
|
|
||||||
update_connector_shape();
|
update_connector_shape();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GLGizmoCut3D::get_tooltip() const
|
std::string GLGizmoCut3D::get_tooltip() const
|
||||||
{
|
{
|
||||||
std::string tooltip;
|
std::string tooltip;
|
||||||
if (m_hover_id == Z) {
|
if (m_hover_id == Z || (m_dragging && m_hover_id == CutPlane)) {
|
||||||
double koef = m_imperial_units ? ObjectManipulation::mm_to_in : 1.0;
|
double koef = m_imperial_units ? ObjectManipulation::mm_to_in : 1.0;
|
||||||
std::string unit_str = " " + (m_imperial_units ? _u8L("inch") : _u8L("mm"));
|
std::string unit_str = " " + (m_imperial_units ? _u8L("inch") : _u8L("mm"));
|
||||||
const BoundingBoxf3 tbb = transformed_bounding_box(m_plane_center);
|
const BoundingBoxf3 tbb = transformed_bounding_box(m_plane_center);
|
||||||
@ -249,6 +257,11 @@ std::string GLGizmoCut3D::get_tooltip() const
|
|||||||
}
|
}
|
||||||
return tooltip;
|
return tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_dragging && m_hover_id == CutPlane)
|
||||||
|
return _u8L("Click to flip the cut plane\n"
|
||||||
|
"Drag to move the cut plane");
|
||||||
|
|
||||||
if (tooltip.empty() && (m_hover_id == X || m_hover_id == Y)) {
|
if (tooltip.empty() && (m_hover_id == X || m_hover_id == Y)) {
|
||||||
std::string axis = m_hover_id == X ? "X" : "Y";
|
std::string axis = m_hover_id == X ? "X" : "Y";
|
||||||
return axis + ": " + format(float(rad2deg(m_angle)), 1) + _u8L("°");
|
return axis + ": " + format(float(rad2deg(m_angle)), 1) + _u8L("°");
|
||||||
@ -264,6 +277,8 @@ bool GLGizmoCut3D::on_mouse(const wxMouseEvent &mouse_event)
|
|||||||
|
|
||||||
if (mouse_event.ShiftDown() && mouse_event.LeftDown())
|
if (mouse_event.ShiftDown() && mouse_event.LeftDown())
|
||||||
return gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, mouse_event.ShiftDown(), mouse_event.AltDown(), mouse_event.CmdDown());
|
return gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, mouse_event.ShiftDown(), mouse_event.AltDown(), mouse_event.CmdDown());
|
||||||
|
if (mouse_event.CmdDown() && mouse_event.LeftDown())
|
||||||
|
return false;
|
||||||
if (cut_line_processing()) {
|
if (cut_line_processing()) {
|
||||||
if (mouse_event.ShiftDown()) {
|
if (mouse_event.ShiftDown()) {
|
||||||
if (mouse_event.Moving()|| mouse_event.Dragging())
|
if (mouse_event.Moving()|| mouse_event.Dragging())
|
||||||
@ -278,11 +293,17 @@ bool GLGizmoCut3D::on_mouse(const wxMouseEvent &mouse_event)
|
|||||||
|
|
||||||
if (use_grabbers(mouse_event)) {
|
if (use_grabbers(mouse_event)) {
|
||||||
if (m_hover_id >= m_connectors_group_id) {
|
if (m_hover_id >= m_connectors_group_id) {
|
||||||
if (mouse_event.LeftDown() && !mouse_event.CmdDown()&& !mouse_event.AltDown())
|
if (mouse_event.LeftDown() && !mouse_event.CmdDown() && !mouse_event.AltDown())
|
||||||
unselect_all_connectors();
|
unselect_all_connectors();
|
||||||
if (mouse_event.LeftUp() && !mouse_event.ShiftDown())
|
if (mouse_event.LeftUp() && !mouse_event.ShiftDown())
|
||||||
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, mouse_event.ShiftDown(), mouse_event.AltDown(), mouse_event.CmdDown());
|
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, mouse_event.ShiftDown(), mouse_event.AltDown(), mouse_event.CmdDown());
|
||||||
}
|
}
|
||||||
|
else if (m_hover_id == CutPlane) {
|
||||||
|
if (mouse_event.LeftDown())
|
||||||
|
m_was_cut_plane_dragged = false;
|
||||||
|
else if (mouse_event.LeftUp() && !m_was_cut_plane_dragged)
|
||||||
|
flip_cut_plane();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,9 +413,18 @@ void GLGizmoCut3D::update_clipper()
|
|||||||
|
|
||||||
// calculate normal for cut plane
|
// calculate normal for cut plane
|
||||||
Vec3d normal = m_cut_normal = end - beg;
|
Vec3d normal = m_cut_normal = end - beg;
|
||||||
m_cut_normal.normalize();
|
|
||||||
|
// calculate normal and offset for clipping plane
|
||||||
|
double dist = (m_plane_center - beg).norm();
|
||||||
|
dist = std::clamp(dist, 0.0001, normal.norm());
|
||||||
|
normal.normalize();
|
||||||
|
m_clp_normal = normal;
|
||||||
|
double offset = normal.dot(beg) + dist;
|
||||||
|
|
||||||
|
m_parent.set_color_clip_plane(normal, offset);
|
||||||
|
|
||||||
if (!is_looking_forward()) {
|
if (!is_looking_forward()) {
|
||||||
|
// recalculate normal and offset for clipping plane, if camera is looking downward to cut plane
|
||||||
end = beg = m_plane_center;
|
end = beg = m_plane_center;
|
||||||
beg[Z] = box.center().z() + m_radius;
|
beg[Z] = box.center().z() + m_radius;
|
||||||
end[Z] = box.center().z() - m_radius;
|
end[Z] = box.center().z() - m_radius;
|
||||||
@ -402,18 +432,16 @@ void GLGizmoCut3D::update_clipper()
|
|||||||
rotate_vec3d_around_plane_center(beg);
|
rotate_vec3d_around_plane_center(beg);
|
||||||
rotate_vec3d_around_plane_center(end);
|
rotate_vec3d_around_plane_center(end);
|
||||||
|
|
||||||
// recalculate normal for clipping plane, if camera is looking downward to cut plane
|
|
||||||
normal = end - beg;
|
normal = end - beg;
|
||||||
if (normal == Vec3d::Zero())
|
if (normal == Vec3d::Zero())
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// calculate normal and offset for clipping plane
|
dist = (m_plane_center - beg).norm();
|
||||||
double dist = (m_plane_center - beg).norm();
|
dist = std::clamp(dist, 0.0001, normal.norm());
|
||||||
dist = std::clamp(dist, 0.0001, normal.norm());
|
normal.normalize();
|
||||||
normal.normalize();
|
m_clp_normal = normal;
|
||||||
m_clp_normal = normal;
|
offset = normal.dot(beg) + dist;
|
||||||
const double offset = normal.dot(beg) + dist;
|
}
|
||||||
|
|
||||||
m_c->object_clipper()->set_range_and_pos(normal, offset, dist);
|
m_c->object_clipper()->set_range_and_pos(normal, offset, dist);
|
||||||
|
|
||||||
@ -656,12 +684,15 @@ void GLGizmoCut3D::render_cut_plane()
|
|||||||
shader->set_uniform("view_model_matrix", view_model_matrix);
|
shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
|
|
||||||
if (can_perform_cut() && has_valid_contour())
|
if (can_perform_cut() && has_valid_contour()) {
|
||||||
// m_plane.set_color({ 0.8f, 0.8f, 0.8f, 0.5f });
|
if (m_hover_id == CutPlane)
|
||||||
m_plane.set_color({ 0.9f, 0.9f, 0.9f, 0.5f });
|
m_plane.model.set_color({ 0.9f, 0.9f, 0.9f, 0.5f });
|
||||||
|
else
|
||||||
|
m_plane.model.set_color({ 0.8f, 0.8f, 0.8f, 0.5f });
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_plane.set_color({ 1.0f, 0.8f, 0.8f, 0.5f });
|
m_plane.model.set_color({ 1.0f, 0.8f, 0.8f, 0.5f });
|
||||||
m_plane.render();
|
m_plane.model.render();
|
||||||
|
|
||||||
glsafe(::glEnable(GL_CULL_FACE));
|
glsafe(::glEnable(GL_CULL_FACE));
|
||||||
glsafe(::glDisable(GL_BLEND));
|
glsafe(::glDisable(GL_BLEND));
|
||||||
@ -717,7 +748,7 @@ void GLGizmoCut3D::render_line(GLModel& line_model, const ColorRGBA& color, Tran
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoCut3D::render_rotation_snapping(Axis axis, const ColorRGBA& color)
|
void GLGizmoCut3D::render_rotation_snapping(GrabberID axis, const ColorRGBA& color)
|
||||||
{
|
{
|
||||||
GLShaderProgram* line_shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
|
GLShaderProgram* line_shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
|
||||||
if (!line_shader)
|
if (!line_shader)
|
||||||
@ -760,49 +791,34 @@ void GLGizmoCut3D::render_cut_plane_grabbers()
|
|||||||
{
|
{
|
||||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
|
|
||||||
ColorRGBA color = m_hover_id == Z ? complementary(GRABBER_COLOR) : GRABBER_COLOR;
|
ColorRGBA color = ColorRGBA::GRAY();
|
||||||
|
|
||||||
const Transform3d view_matrix = wxGetApp().plater()->get_camera().get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m;
|
const Transform3d view_matrix = wxGetApp().plater()->get_camera().get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m;
|
||||||
|
|
||||||
const double mean_size = get_grabber_mean_size(bounding_box());
|
const double mean_size = get_grabber_mean_size(bounding_box());
|
||||||
|
double size;
|
||||||
|
|
||||||
double size = m_dragging && m_hover_id == Z ? get_dragging_half_size(mean_size) : get_half_size(mean_size);
|
const bool dragging_by_cut_plane = m_dragging && m_hover_id == CutPlane;
|
||||||
|
|
||||||
Vec3d cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
|
if (!dragging_by_cut_plane) {
|
||||||
Vec3d offset = 1.25 * size * Vec3d::UnitZ();
|
render_grabber_connection(GRABBER_COLOR, view_matrix);
|
||||||
|
|
||||||
// render Z grabber
|
// render sphere grabber
|
||||||
|
|
||||||
if (!m_dragging && m_hover_id < 0)
|
|
||||||
render_grabber_connection(color, view_matrix);
|
|
||||||
render_model(m_sphere.model, color, view_matrix * scale_transform(size));
|
|
||||||
|
|
||||||
if ((!m_dragging && m_hover_id < 0) || m_hover_id == Z)
|
|
||||||
{
|
|
||||||
const BoundingBoxf3 tbb = transformed_bounding_box(m_plane_center);
|
|
||||||
if (tbb.min.z() <= 0.0)
|
|
||||||
render_model(m_cone.model, color, view_matrix * translation_transform(-offset) * rotation_transform(PI * Vec3d::UnitX()) * scale_transform(cone_scale));
|
|
||||||
|
|
||||||
if (tbb.max.z() >= 0.0)
|
|
||||||
render_model(m_cone.model, color, view_matrix * translation_transform(offset) * scale_transform(cone_scale));
|
|
||||||
}
|
|
||||||
|
|
||||||
// render top sphere for X/Y grabbers
|
|
||||||
|
|
||||||
if ((!m_dragging && m_hover_id < 0) || m_hover_id == X || m_hover_id == Y)
|
|
||||||
{
|
|
||||||
size = m_dragging ? get_dragging_half_size(mean_size) : get_half_size(mean_size);
|
size = m_dragging ? get_dragging_half_size(mean_size) : get_half_size(mean_size);
|
||||||
color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) :
|
color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) :
|
||||||
m_hover_id == X ? complementary(ColorRGBA::RED()) : ColorRGBA::GRAY();
|
m_hover_id == X ? complementary(ColorRGBA::RED()) :
|
||||||
|
m_hover_id == Z ? GRABBER_COLOR : ColorRGBA::GRAY();
|
||||||
render_model(m_sphere.model, color, view_matrix * translation_transform(m_grabber_connection_len * Vec3d::UnitZ()) * scale_transform(size));
|
render_model(m_sphere.model, color, view_matrix * translation_transform(m_grabber_connection_len * Vec3d::UnitZ()) * scale_transform(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool no_one_grabber_hovered = !m_dragging && (m_hover_id < 0 || m_hover_id == CutPlane);
|
||||||
|
|
||||||
// render X grabber
|
// render X grabber
|
||||||
|
|
||||||
if ((!m_dragging && m_hover_id < 0) || m_hover_id == X)
|
if (no_one_grabber_hovered || m_hover_id == X)
|
||||||
{
|
{
|
||||||
size = m_dragging && m_hover_id == X ? get_dragging_half_size(mean_size) : get_half_size(mean_size);
|
size = m_dragging && m_hover_id == X ? get_dragging_half_size(mean_size) : get_half_size(mean_size);
|
||||||
cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
|
const Vec3d cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
|
||||||
color = m_hover_id == X ? complementary(ColorRGBA::RED()) : ColorRGBA::RED();
|
color = m_hover_id == X ? complementary(ColorRGBA::RED()) : ColorRGBA::RED();
|
||||||
|
|
||||||
if (m_hover_id == X) {
|
if (m_hover_id == X) {
|
||||||
@ -810,7 +826,7 @@ void GLGizmoCut3D::render_cut_plane_grabbers()
|
|||||||
render_rotation_snapping(X, color);
|
render_rotation_snapping(X, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = Vec3d(0.0, 1.25 * size, m_grabber_connection_len);
|
Vec3d offset = Vec3d(0.0, 1.25 * size, m_grabber_connection_len);
|
||||||
render_model(m_cone.model, color, view_matrix * translation_transform(offset) * rotation_transform(-0.5 * PI * Vec3d::UnitX()) * scale_transform(cone_scale));
|
render_model(m_cone.model, color, view_matrix * translation_transform(offset) * rotation_transform(-0.5 * PI * Vec3d::UnitX()) * scale_transform(cone_scale));
|
||||||
offset = Vec3d(0.0, -1.25 * size, m_grabber_connection_len);
|
offset = Vec3d(0.0, -1.25 * size, m_grabber_connection_len);
|
||||||
render_model(m_cone.model, color, view_matrix * translation_transform(offset) * rotation_transform(0.5 * PI * Vec3d::UnitX()) * scale_transform(cone_scale));
|
render_model(m_cone.model, color, view_matrix * translation_transform(offset) * rotation_transform(0.5 * PI * Vec3d::UnitX()) * scale_transform(cone_scale));
|
||||||
@ -818,10 +834,10 @@ void GLGizmoCut3D::render_cut_plane_grabbers()
|
|||||||
|
|
||||||
// render Y grabber
|
// render Y grabber
|
||||||
|
|
||||||
if ((!m_dragging && m_hover_id < 0) || m_hover_id == Y)
|
if (no_one_grabber_hovered || m_hover_id == Y)
|
||||||
{
|
{
|
||||||
size = m_dragging && m_hover_id == Y ? get_dragging_half_size(mean_size) : get_half_size(mean_size);
|
size = m_dragging && m_hover_id == Y ? get_dragging_half_size(mean_size) : get_half_size(mean_size);
|
||||||
cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
|
const Vec3d cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
|
||||||
color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) : ColorRGBA::GREEN();
|
color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) : ColorRGBA::GREEN();
|
||||||
|
|
||||||
if (m_hover_id == Y) {
|
if (m_hover_id == Y) {
|
||||||
@ -829,7 +845,7 @@ void GLGizmoCut3D::render_cut_plane_grabbers()
|
|||||||
render_rotation_snapping(Y, color);
|
render_rotation_snapping(Y, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = Vec3d(1.25 * size, 0.0, m_grabber_connection_len);
|
Vec3d offset = Vec3d(1.25 * size, 0.0, m_grabber_connection_len);
|
||||||
render_model(m_cone.model, color, view_matrix * translation_transform(offset) * rotation_transform(0.5 * PI * Vec3d::UnitY()) * scale_transform(cone_scale));
|
render_model(m_cone.model, color, view_matrix * translation_transform(offset) * rotation_transform(0.5 * PI * Vec3d::UnitY()) * scale_transform(cone_scale));
|
||||||
offset = Vec3d(-1.25 * size, 0.0, m_grabber_connection_len);
|
offset = Vec3d(-1.25 * size, 0.0, m_grabber_connection_len);
|
||||||
render_model(m_cone.model, color, view_matrix * translation_transform(offset)* rotation_transform(-0.5 * PI * Vec3d::UnitY()) * scale_transform(cone_scale));
|
render_model(m_cone.model, color, view_matrix * translation_transform(offset)* rotation_transform(-0.5 * PI * Vec3d::UnitY()) * scale_transform(cone_scale));
|
||||||
@ -898,6 +914,9 @@ std::string GLGizmoCut3D::on_get_name() const
|
|||||||
void GLGizmoCut3D::on_set_state()
|
void GLGizmoCut3D::on_set_state()
|
||||||
{
|
{
|
||||||
if (m_state == On) {
|
if (m_state == On) {
|
||||||
|
m_parent.set_use_color_clip_plane(true);
|
||||||
|
m_parent.set_color_clip_plane_colors({ UPPER_PART_COLOR , LOWER_PART_COLOR });
|
||||||
|
|
||||||
update_bb();
|
update_bb();
|
||||||
m_connectors_editing = !m_selected.empty();
|
m_connectors_editing = !m_selected.empty();
|
||||||
|
|
||||||
@ -913,6 +932,7 @@ void GLGizmoCut3D::on_set_state()
|
|||||||
oc->release();
|
oc->release();
|
||||||
}
|
}
|
||||||
m_selected.clear();
|
m_selected.clear();
|
||||||
|
m_parent.set_use_color_clip_plane(false);
|
||||||
}
|
}
|
||||||
force_update_clipper_on_render = m_state == On;
|
force_update_clipper_on_render = m_state == On;
|
||||||
}
|
}
|
||||||
@ -940,8 +960,8 @@ void GLGizmoCut3D::on_register_raycasters_for_picking()
|
|||||||
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, Y, *m_cone.mesh_raycaster, Transform3d::Identity()));
|
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, Y, *m_cone.mesh_raycaster, Transform3d::Identity()));
|
||||||
|
|
||||||
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, Z, *m_sphere.mesh_raycaster, Transform3d::Identity()));
|
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, Z, *m_sphere.mesh_raycaster, Transform3d::Identity()));
|
||||||
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, Z, *m_cone.mesh_raycaster, Transform3d::Identity()));
|
|
||||||
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, Z, *m_cone.mesh_raycaster, Transform3d::Identity()));
|
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, CutPlane, *m_plane.mesh_raycaster, Transform3d::Identity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
update_raycasters_for_picking_transform();
|
update_raycasters_for_picking_transform();
|
||||||
@ -1018,20 +1038,22 @@ void GLGizmoCut3D::update_raycasters_for_picking_transform()
|
|||||||
const double size = get_half_size(get_grabber_mean_size(box));
|
const double size = get_half_size(get_grabber_mean_size(box));
|
||||||
Vec3d scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
|
Vec3d scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
|
||||||
|
|
||||||
|
int id = 0;
|
||||||
|
|
||||||
Vec3d offset = Vec3d(0.0, 1.25 * size, m_grabber_connection_len);
|
Vec3d offset = Vec3d(0.0, 1.25 * size, m_grabber_connection_len);
|
||||||
m_raycasters[0]->set_transform(trafo * translation_transform(offset) * rotation_transform(-0.5 * PI * Vec3d::UnitX()) * scale_transform(scale));
|
m_raycasters[id++]->set_transform(trafo * translation_transform(offset) * rotation_transform(-0.5 * PI * Vec3d::UnitX()) * scale_transform(scale));
|
||||||
offset = Vec3d(0.0, -1.25 * size, m_grabber_connection_len);
|
offset = Vec3d(0.0, -1.25 * size, m_grabber_connection_len);
|
||||||
m_raycasters[1]->set_transform(trafo * translation_transform(offset) * rotation_transform(0.5 * PI * Vec3d::UnitX()) * scale_transform(scale));
|
m_raycasters[id++]->set_transform(trafo * translation_transform(offset) * rotation_transform(0.5 * PI * Vec3d::UnitX()) * scale_transform(scale));
|
||||||
|
|
||||||
offset = Vec3d(1.25 * size, 0.0, m_grabber_connection_len);
|
offset = Vec3d(1.25 * size, 0.0, m_grabber_connection_len);
|
||||||
m_raycasters[2]->set_transform(trafo * translation_transform(offset) * rotation_transform(0.5 * PI * Vec3d::UnitY()) * scale_transform(scale));
|
m_raycasters[id++]->set_transform(trafo * translation_transform(offset) * rotation_transform(0.5 * PI * Vec3d::UnitY()) * scale_transform(scale));
|
||||||
offset = Vec3d(-1.25 * size, 0.0, m_grabber_connection_len);
|
offset = Vec3d(-1.25 * size, 0.0, m_grabber_connection_len);
|
||||||
m_raycasters[3]->set_transform(trafo * translation_transform(offset) * rotation_transform(-0.5 * PI * Vec3d::UnitY()) * scale_transform(scale));
|
m_raycasters[id++]->set_transform(trafo * translation_transform(offset) * rotation_transform(-0.5 * PI * Vec3d::UnitY()) * scale_transform(scale));
|
||||||
|
|
||||||
offset = 1.25 * size * Vec3d::UnitZ();
|
offset = 1.25 * size * Vec3d::UnitZ();
|
||||||
m_raycasters[4]->set_transform(trafo * scale_transform(size));
|
m_raycasters[id++]->set_transform(trafo * translation_transform(m_grabber_connection_len * Vec3d::UnitZ()) * scale_transform(size));
|
||||||
m_raycasters[5]->set_transform(trafo * translation_transform(-offset) * rotation_transform(PI * Vec3d::UnitX()) * scale_transform(scale));
|
|
||||||
m_raycasters[6]->set_transform(trafo * translation_transform(offset) * scale_transform(scale));
|
m_raycasters[id++]->set_transform(trafo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1072,7 +1094,7 @@ bool GLGizmoCut3D::on_is_selectable() const
|
|||||||
return wxGetApp().get_mode() != comSimple;
|
return wxGetApp().get_mode() != comSimple;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3d GLGizmoCut3D::mouse_position_in_local_plane(Axis axis, const Linef3& mouse_ray) const
|
Vec3d GLGizmoCut3D::mouse_position_in_local_plane(GrabberID axis, const Linef3& mouse_ray) const
|
||||||
{
|
{
|
||||||
double half_pi = 0.5 * PI;
|
double half_pi = 0.5 * PI;
|
||||||
|
|
||||||
@ -1108,13 +1130,11 @@ Vec3d GLGizmoCut3D::mouse_position_in_local_plane(Axis axis, const Linef3& mouse
|
|||||||
|
|
||||||
void GLGizmoCut3D::dragging_grabber_z(const GLGizmoBase::UpdateData &data)
|
void GLGizmoCut3D::dragging_grabber_z(const GLGizmoBase::UpdateData &data)
|
||||||
{
|
{
|
||||||
Vec3d starting_box_center = m_plane_center - Vec3d::UnitZ(); // some Margin
|
const Vec3d grabber_init_pos = (m_hover_id == CutPlane ? 0. : m_grabber_connection_len) * Vec3d::UnitZ();
|
||||||
rotate_vec3d_around_plane_center(starting_box_center);
|
const Vec3d starting_drag_position = translation_transform(m_plane_center) * m_rotation_m * grabber_init_pos;
|
||||||
|
double projection = 0.0;
|
||||||
|
|
||||||
const Vec3d&starting_drag_position = m_plane_center;
|
Vec3d starting_vec = m_rotation_m * Vec3d::UnitZ();
|
||||||
double projection = 0.0;
|
|
||||||
|
|
||||||
Vec3d starting_vec = starting_drag_position - starting_box_center;
|
|
||||||
if (starting_vec.norm() != 0.0) {
|
if (starting_vec.norm() != 0.0) {
|
||||||
const Vec3d mouse_dir = data.mouse_ray.unit_vector();
|
const Vec3d mouse_dir = data.mouse_ray.unit_vector();
|
||||||
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
|
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
|
||||||
@ -1130,17 +1150,19 @@ void GLGizmoCut3D::dragging_grabber_z(const GLGizmoBase::UpdateData &data)
|
|||||||
projection = inters_vec.dot(starting_vec);
|
projection = inters_vec.dot(starting_vec);
|
||||||
}
|
}
|
||||||
if (wxGetKeyState(WXK_SHIFT))
|
if (wxGetKeyState(WXK_SHIFT))
|
||||||
projection = m_snap_step * (double)std::round(projection / m_snap_step);
|
projection = m_snap_step * std::round(projection / m_snap_step);
|
||||||
|
|
||||||
const Vec3d shift = starting_vec * projection;
|
const Vec3d shift = starting_vec * projection;
|
||||||
|
|
||||||
// move cut plane center
|
// move cut plane center
|
||||||
set_center(m_plane_center + shift);
|
set_center(m_plane_center + shift);
|
||||||
|
|
||||||
|
m_was_cut_plane_dragged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoCut3D::dragging_grabber_xy(const GLGizmoBase::UpdateData &data)
|
void GLGizmoCut3D::dragging_grabber_xy(const GLGizmoBase::UpdateData &data)
|
||||||
{
|
{
|
||||||
const Vec2d mouse_pos = to_2d(mouse_position_in_local_plane((Axis)m_hover_id, data.mouse_ray));
|
const Vec2d mouse_pos = to_2d(mouse_position_in_local_plane((GrabberID)m_hover_id, data.mouse_ray));
|
||||||
|
|
||||||
const Vec2d orig_dir = Vec2d::UnitX();
|
const Vec2d orig_dir = Vec2d::UnitX();
|
||||||
const Vec2d new_dir = mouse_pos.normalized();
|
const Vec2d new_dir = mouse_pos.normalized();
|
||||||
@ -1197,7 +1219,7 @@ void GLGizmoCut3D::on_dragging(const UpdateData& data)
|
|||||||
{
|
{
|
||||||
if (m_hover_id < 0)
|
if (m_hover_id < 0)
|
||||||
return;
|
return;
|
||||||
if (m_hover_id == Z)
|
if (m_hover_id == Z || m_hover_id == CutPlane)
|
||||||
dragging_grabber_z(data);
|
dragging_grabber_z(data);
|
||||||
else if (m_hover_id == X || m_hover_id == Y)
|
else if (m_hover_id == X || m_hover_id == Y)
|
||||||
dragging_grabber_xy(data);
|
dragging_grabber_xy(data);
|
||||||
@ -1223,8 +1245,9 @@ void GLGizmoCut3D::on_stop_dragging()
|
|||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Rotate cut plane"), UndoRedo::SnapshotType::GizmoAction);
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Rotate cut plane"), UndoRedo::SnapshotType::GizmoAction);
|
||||||
m_start_dragging_m = m_rotation_m;
|
m_start_dragging_m = m_rotation_m;
|
||||||
}
|
}
|
||||||
else if (m_hover_id == Z) {
|
else if (m_hover_id == Z || m_hover_id == CutPlane) {
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Move cut plane"), UndoRedo::SnapshotType::GizmoAction);
|
if (m_was_cut_plane_dragged)
|
||||||
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Move cut plane"), UndoRedo::SnapshotType::GizmoAction);
|
||||||
m_ar_plane_center = m_plane_center;
|
m_ar_plane_center = m_plane_center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1332,7 +1355,7 @@ bool GLGizmoCut3D::update_bb()
|
|||||||
set_center_pos(m_bb_center, true);
|
set_center_pos(m_bb_center, true);
|
||||||
|
|
||||||
m_radius = box.radius();
|
m_radius = box.radius();
|
||||||
m_grabber_connection_len = 0.75 * m_radius;// std::min<double>(0.75 * m_radius, 35.0);
|
m_grabber_connection_len = 0.5 * m_radius;// std::min<double>(0.75 * m_radius, 35.0);
|
||||||
m_grabber_radius = m_grabber_connection_len * 0.85;
|
m_grabber_radius = m_grabber_connection_len * 0.85;
|
||||||
|
|
||||||
m_snap_coarse_in_radius = m_grabber_radius / 3.0;
|
m_snap_coarse_in_radius = m_grabber_radius / 3.0;
|
||||||
@ -1372,6 +1395,14 @@ void GLGizmoCut3D::init_picking_models()
|
|||||||
m_sphere.model.init_from(its);
|
m_sphere.model.init_from(its);
|
||||||
m_sphere.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
m_sphere.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_plane.model.is_initialized() && !m_hide_cut_plane && !m_connectors_editing) {
|
||||||
|
const double cp_width = 0.02 * get_grabber_mean_size(bounding_box());
|
||||||
|
indexed_triangle_set its = its_make_frustum_dowel((double)m_cut_plane_radius_koef * m_radius, cp_width, m_cut_plane_as_circle ? 180 : 4);
|
||||||
|
m_plane.model.init_from(its);
|
||||||
|
m_plane.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
||||||
|
}
|
||||||
|
|
||||||
if (m_shapes.empty())
|
if (m_shapes.empty())
|
||||||
init_connector_shapes();
|
init_connector_shapes();
|
||||||
}
|
}
|
||||||
@ -1392,18 +1423,6 @@ void GLGizmoCut3D::init_rendering_items()
|
|||||||
}
|
}
|
||||||
if (!m_angle_arc.is_initialized() || m_angle != 0.0)
|
if (!m_angle_arc.is_initialized() || m_angle != 0.0)
|
||||||
init_from_angle_arc(m_angle_arc, m_angle, m_grabber_connection_len);
|
init_from_angle_arc(m_angle_arc, m_angle, m_grabber_connection_len);
|
||||||
|
|
||||||
if (!m_plane.is_initialized() && !m_hide_cut_plane && !m_connectors_editing) {
|
|
||||||
#if 1
|
|
||||||
const double cp_width = 0.02 * get_grabber_mean_size(bounding_box());
|
|
||||||
m_plane.init_from(its_make_frustum_dowel((double)m_cut_plane_radius_koef * m_radius, cp_width, m_cut_plane_as_circle ? 180 : 4));
|
|
||||||
#else
|
|
||||||
if (m_cut_plane_as_circle)
|
|
||||||
m_plane.init_from(its_make_frustum_dowel(2. * m_radius, 0.3, 180));
|
|
||||||
else
|
|
||||||
m_plane.init_from(its_make_square_plane(float(m_radius)));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoCut3D::render_clipper_cut()
|
void GLGizmoCut3D::render_clipper_cut()
|
||||||
@ -1566,6 +1585,8 @@ void GLGizmoCut3D::render_connectors_input_window(CutConnectors &connectors)
|
|||||||
reset_connectors();
|
reset_connectors();
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
|
render_flip_plane_button(m_connectors_editing && connectors.empty());
|
||||||
|
|
||||||
m_imgui->text(_L("Type"));
|
m_imgui->text(_L("Type"));
|
||||||
bool type_changed = render_connect_type_radio_button(CutConnectorType::Plug);
|
bool type_changed = render_connect_type_radio_button(CutConnectorType::Plug);
|
||||||
type_changed |= render_connect_type_radio_button(CutConnectorType::Dowel);
|
type_changed |= render_connect_type_radio_button(CutConnectorType::Dowel);
|
||||||
@ -1660,6 +1681,57 @@ void GLGizmoCut3D::set_connectors_editing(bool connectors_editing)
|
|||||||
m_parent.request_extra_frame();
|
m_parent.request_extra_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoCut3D::flip_cut_plane()
|
||||||
|
{
|
||||||
|
m_rotation_m = m_rotation_m * rotation_transform(PI * Vec3d::UnitX());
|
||||||
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Flip cut plane"), UndoRedo::SnapshotType::GizmoAction);
|
||||||
|
m_start_dragging_m = m_rotation_m;
|
||||||
|
|
||||||
|
update_clipper();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoCut3D::render_flip_plane_button(bool disable_pred /*=false*/)
|
||||||
|
{
|
||||||
|
ImGui::SameLine(2.5 * m_label_width);
|
||||||
|
|
||||||
|
if (m_hover_id == CutPlane)
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetColorU32(ImGuiCol_ButtonHovered));
|
||||||
|
|
||||||
|
m_imgui->disabled_begin(disable_pred);
|
||||||
|
if (m_imgui->button(_L("Flip cut plane")))
|
||||||
|
flip_cut_plane();
|
||||||
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
|
if (m_hover_id == CutPlane)
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoCut3D::add_vertical_scaled_interval(float interval)
|
||||||
|
{
|
||||||
|
ImGui::GetCurrentWindow()->DC.CursorPos.y += m_imgui->scaled(interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoCut3D::add_horizontal_scaled_interval(float interval)
|
||||||
|
{
|
||||||
|
ImGui::GetCurrentWindow()->DC.CursorPos.x += m_imgui->scaled(interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoCut3D::add_horizontal_shift(float shift)
|
||||||
|
{
|
||||||
|
ImGui::GetCurrentWindow()->DC.CursorPos.x += shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoCut3D::render_color_marker(float size, const ImU32& color)
|
||||||
|
{
|
||||||
|
ImGui::SameLine();
|
||||||
|
const float radius = 0.5f * size;
|
||||||
|
ImVec2 pos = ImGui::GetCurrentWindow()->DC.CursorPos;
|
||||||
|
pos.x += size;
|
||||||
|
pos.y += 1.25f * radius;
|
||||||
|
ImGui::GetCurrentWindow()->DrawList->AddNgonFilled(pos, radius, color, 6);
|
||||||
|
ImGuiWrapper::text(" ");
|
||||||
|
}
|
||||||
|
|
||||||
void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
|
void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
|
||||||
{
|
{
|
||||||
// WIP : cut plane mode
|
// WIP : cut plane mode
|
||||||
@ -1667,65 +1739,130 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
|
|||||||
|
|
||||||
if (m_mode == size_t(CutMode::cutPlanar)) {
|
if (m_mode == size_t(CutMode::cutPlanar)) {
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
m_imgui->text(wxString(ImGui::InfoMarkerSmall));
|
ImGuiWrapper::text(wxString(ImGui::InfoMarkerSmall));
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT,
|
ImGuiWrapper::text_colored(ImGuiWrapper::COL_ORANGE_LIGHT,
|
||||||
get_wraped_wxString(_L("Hold SHIFT key and connect some two points of an object to cut by line"), 40));
|
get_wraped_wxString(_L("Hold SHIFT key to draw a cut line"), 40));
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
render_build_size();
|
render_build_size();
|
||||||
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
m_imgui->text(_L("Cut position: "));
|
ImGuiWrapper::text(_L("Cut position: "));
|
||||||
ImGui::SameLine(m_label_width);
|
ImGui::SameLine(m_label_width);
|
||||||
render_move_center_input(Z);
|
render_move_center_input(Z);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
const bool has_connectors = !connectors.empty();
|
||||||
|
|
||||||
const bool is_cut_plane_init = m_rotation_m.isApprox(Transform3d::Identity()) && bounding_box().center() == m_plane_center;
|
const bool is_cut_plane_init = m_rotation_m.isApprox(Transform3d::Identity()) && bounding_box().center() == m_plane_center;
|
||||||
m_imgui->disabled_begin(is_cut_plane_init);
|
m_imgui->disabled_begin(is_cut_plane_init);
|
||||||
if (render_reset_button("cut_plane", _u8L("Reset cutting plane")))
|
if (render_reset_button("cut_plane", _u8L("Reset cutting plane")))
|
||||||
reset_cut_plane();
|
reset_cut_plane();
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
m_imgui->disabled_begin(!m_keep_upper || !m_keep_lower);
|
// render_flip_plane_button();
|
||||||
if (m_imgui->button(_L("Add/Edit connectors")))
|
|
||||||
|
add_vertical_scaled_interval(0.75f);
|
||||||
|
|
||||||
|
m_imgui->disabled_begin(!m_keep_upper || !m_keep_lower || m_keep_as_parts);
|
||||||
|
if (m_imgui->button(has_connectors ? _L("Edit connectors") : _L("Add connectors")))
|
||||||
set_connectors_editing(true);
|
set_connectors_editing(true);
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
|
ImGui::SameLine(2.5f * m_label_width);
|
||||||
|
|
||||||
|
m_imgui->disabled_begin(is_cut_plane_init && !has_connectors);
|
||||||
|
if (m_imgui->button(_L("Reset cut"), _L("Reset cutting plane and remove connectors"))) {
|
||||||
|
reset_cut_plane();
|
||||||
|
reset_connectors();
|
||||||
|
}
|
||||||
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
float label_width = 0;
|
// render "After Cut" section
|
||||||
for (const wxString& label : {_L("Upper part"), _L("Lower part")}) {
|
|
||||||
const float width = m_imgui->calc_text_size(label).x + m_imgui->scaled(1.5f);
|
ImVec2 label_size;
|
||||||
if (label_width < width)
|
for (const auto& item : m_part_orientation_names) {
|
||||||
label_width = width;
|
const ImVec2 text_size = ImGuiWrapper::calc_text_size(item.second);
|
||||||
|
if (label_size.x < text_size.x)
|
||||||
|
label_size.x = text_size.x;
|
||||||
|
if (label_size.y < text_size.y)
|
||||||
|
label_size.y = text_size.y;
|
||||||
}
|
}
|
||||||
|
const float h_shift = label_size.x + m_imgui->scaled(3.f);
|
||||||
|
const float marker_size = label_size.y;
|
||||||
|
|
||||||
auto render_part_action_line = [this, label_width, connectors](const wxString& label, const wxString& suffix, bool& keep_part, bool& place_on_cut_part, bool& rotate_part) {
|
auto render_part_name = [this, marker_size, has_connectors](const wxString& name, bool& keep_part, const ImU32& color) {
|
||||||
bool keep = true;
|
bool keep = true;
|
||||||
ImGui::AlignTextToFramePadding();
|
add_horizontal_shift(m_imgui->scaled(1.2f));
|
||||||
m_imgui->text(label);
|
m_imgui->checkbox((m_keep_as_parts ? _L("Part") : _L("Object")) + " " + name, has_connectors ? keep : keep_part);
|
||||||
|
render_color_marker(marker_size, color);
|
||||||
|
};
|
||||||
|
|
||||||
ImGui::SameLine(label_width);
|
auto render_part_actions = [this, h_shift] (const wxString& suffix, const bool& keep_part, bool& place_on_cut_part, bool& rotate_part)
|
||||||
|
{
|
||||||
m_imgui->disabled_begin(!connectors.empty());
|
float shift = m_imgui->scaled(1.2f);
|
||||||
m_imgui->checkbox(_L("Keep") + suffix, connectors.empty() ? keep_part : keep);
|
if (suffix == "##lower")
|
||||||
m_imgui->disabled_end();
|
shift += h_shift;
|
||||||
|
m_imgui->disabled_begin(!keep_part || m_keep_as_parts);
|
||||||
ImGui::SameLine();
|
add_horizontal_shift(shift);
|
||||||
|
if (m_imgui->radio_button(m_part_orientation_names.at("none") + suffix, !place_on_cut_part && !rotate_part)) {
|
||||||
m_imgui->disabled_begin(!keep_part);
|
|
||||||
if (m_imgui->checkbox(_L("Place on cut") + suffix, place_on_cut_part))
|
|
||||||
rotate_part = false;
|
rotate_part = false;
|
||||||
ImGui::SameLine();
|
|
||||||
if (m_imgui->checkbox(_L("Flip") + suffix, rotate_part))
|
|
||||||
place_on_cut_part = false;
|
place_on_cut_part = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_horizontal_shift(shift);
|
||||||
|
if (m_imgui->radio_button(m_part_orientation_names.at("on_cut") + suffix, place_on_cut_part)) {
|
||||||
|
place_on_cut_part = !place_on_cut_part;
|
||||||
|
rotate_part = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_horizontal_shift(shift);
|
||||||
|
if (m_imgui->radio_button(m_part_orientation_names.at("flip") + suffix, rotate_part)) {
|
||||||
|
rotate_part = !rotate_part;
|
||||||
|
place_on_cut_part = false;
|
||||||
|
}
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
};
|
};
|
||||||
|
|
||||||
m_imgui->text(_L("After cut") + ": ");
|
ImGuiWrapper::text(_L("After cut") + ": ");
|
||||||
render_part_action_line( _L("Upper part"), "##upper", m_keep_upper, m_place_on_cut_upper, m_rotate_upper);
|
add_vertical_scaled_interval(0.5f);
|
||||||
render_part_action_line( _L("Lower part"), "##lower", m_keep_lower, m_place_on_cut_lower, m_rotate_lower);
|
|
||||||
|
m_imgui->disabled_begin(has_connectors || m_keep_as_parts);
|
||||||
|
render_part_name("A", m_keep_upper, m_imgui->to_ImU32(UPPER_PART_COLOR));
|
||||||
|
ImGui::SameLine(h_shift + ImGui::GetCurrentWindow()->WindowPadding.x);
|
||||||
|
render_part_name("B", m_keep_lower, m_imgui->to_ImU32(LOWER_PART_COLOR));
|
||||||
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
|
add_vertical_scaled_interval(0.5f);
|
||||||
|
|
||||||
|
const ImVec2 pos = ImGui::GetCurrentWindow()->DC.CursorPos;
|
||||||
|
render_part_actions("##upper", m_keep_upper, m_place_on_cut_upper, m_rotate_upper);
|
||||||
|
|
||||||
|
ImGui::GetCurrentWindow()->DC.CursorPos = pos;
|
||||||
|
render_part_actions("##lower", m_keep_lower, m_place_on_cut_lower, m_rotate_lower);
|
||||||
|
|
||||||
|
add_vertical_scaled_interval(0.75f);
|
||||||
|
|
||||||
|
m_imgui->disabled_begin(has_connectors);
|
||||||
|
add_horizontal_shift(m_imgui->scaled(/*1*/.2f));
|
||||||
|
ImGuiWrapper::text(_L("Cut to") + ":");
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (m_imgui->radio_button(_L("Objects"), !m_keep_as_parts))
|
||||||
|
m_keep_as_parts = false;
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (m_imgui->radio_button(_L("Parts"), m_keep_as_parts))
|
||||||
|
m_keep_as_parts = true;
|
||||||
|
|
||||||
|
if (m_keep_as_parts) {
|
||||||
|
m_keep_upper = m_keep_lower = true;
|
||||||
|
m_place_on_cut_upper = m_place_on_cut_lower = false;
|
||||||
|
m_rotate_upper = m_rotate_lower = false;
|
||||||
|
}
|
||||||
|
m_imgui->disabled_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
@ -2110,11 +2247,13 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
|
|||||||
plater->cut(object_idx, instance_idx, translation_transform(cut_center_offset) * m_rotation_m,
|
plater->cut(object_idx, instance_idx, translation_transform(cut_center_offset) * m_rotation_m,
|
||||||
only_if(has_connectors ? true : m_keep_upper, ModelObjectCutAttribute::KeepUpper) |
|
only_if(has_connectors ? true : m_keep_upper, ModelObjectCutAttribute::KeepUpper) |
|
||||||
only_if(has_connectors ? true : m_keep_lower, ModelObjectCutAttribute::KeepLower) |
|
only_if(has_connectors ? true : m_keep_lower, ModelObjectCutAttribute::KeepLower) |
|
||||||
|
only_if(has_connectors ? false: m_keep_as_parts, ModelObjectCutAttribute::KeepAsParts) |
|
||||||
only_if(m_place_on_cut_upper, ModelObjectCutAttribute::PlaceOnCutUpper) |
|
only_if(m_place_on_cut_upper, ModelObjectCutAttribute::PlaceOnCutUpper) |
|
||||||
only_if(m_place_on_cut_lower, ModelObjectCutAttribute::PlaceOnCutLower) |
|
only_if(m_place_on_cut_lower, ModelObjectCutAttribute::PlaceOnCutLower) |
|
||||||
only_if(m_rotate_upper, ModelObjectCutAttribute::FlipUpper) |
|
only_if(m_rotate_upper, ModelObjectCutAttribute::FlipUpper) |
|
||||||
only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower) |
|
only_if(m_rotate_lower, ModelObjectCutAttribute::FlipLower) |
|
||||||
only_if(create_dowels_as_separate_object, ModelObjectCutAttribute::CreateDowels));
|
only_if(create_dowels_as_separate_object, ModelObjectCutAttribute::CreateDowels) |
|
||||||
|
only_if(!has_connectors, ModelObjectCutAttribute::InvalidateCutInfo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2349,7 +2488,7 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi
|
|||||||
if (is_dragging() || m_connector_mode == CutConnectorMode::Auto)
|
if (is_dragging() || m_connector_mode == CutConnectorMode::Auto)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( m_hover_id < 0 && shift_down && ! m_connectors_editing &&
|
if ( (m_hover_id < 0 || m_hover_id == CutPlane) && shift_down && ! m_connectors_editing &&
|
||||||
(action == SLAGizmoEventType::LeftDown || action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::Moving) )
|
(action == SLAGizmoEventType::LeftDown || action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::Moving) )
|
||||||
return process_cut_line(action, mouse_position);
|
return process_cut_line(action, mouse_position);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "slic3r/GUI/GLModel.hpp"
|
#include "slic3r/GUI/GLModel.hpp"
|
||||||
#include "libslic3r/TriangleMesh.hpp"
|
#include "libslic3r/TriangleMesh.hpp"
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
|
#include "imgui/imgui.h"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
@ -20,6 +21,14 @@ enum class SLAGizmoEventType : unsigned char;
|
|||||||
|
|
||||||
class GLGizmoCut3D : public GLGizmoBase
|
class GLGizmoCut3D : public GLGizmoBase
|
||||||
{
|
{
|
||||||
|
enum GrabberID {
|
||||||
|
X = 0,
|
||||||
|
Y,
|
||||||
|
Z,
|
||||||
|
CutPlane,
|
||||||
|
Count,
|
||||||
|
};
|
||||||
|
|
||||||
Transform3d m_rotation_m{ Transform3d::Identity() };
|
Transform3d m_rotation_m{ Transform3d::Identity() };
|
||||||
double m_snap_step{ 1.0 };
|
double m_snap_step{ 1.0 };
|
||||||
int m_connectors_group_id;
|
int m_connectors_group_id;
|
||||||
@ -57,10 +66,10 @@ class GLGizmoCut3D : public GLGizmoBase
|
|||||||
|
|
||||||
Vec2d m_ldown_mouse_position{ Vec2d::Zero() };
|
Vec2d m_ldown_mouse_position{ Vec2d::Zero() };
|
||||||
|
|
||||||
GLModel m_plane;
|
|
||||||
GLModel m_grabber_connection;
|
GLModel m_grabber_connection;
|
||||||
GLModel m_cut_line;
|
GLModel m_cut_line;
|
||||||
|
|
||||||
|
PickingModel m_plane;
|
||||||
PickingModel m_sphere;
|
PickingModel m_sphere;
|
||||||
PickingModel m_cone;
|
PickingModel m_cone;
|
||||||
std::map<CutConnectorAttributes, PickingModel> m_shapes;
|
std::map<CutConnectorAttributes, PickingModel> m_shapes;
|
||||||
@ -90,6 +99,7 @@ class GLGizmoCut3D : public GLGizmoBase
|
|||||||
|
|
||||||
bool m_keep_upper{ true };
|
bool m_keep_upper{ true };
|
||||||
bool m_keep_lower{ true };
|
bool m_keep_lower{ true };
|
||||||
|
bool m_keep_as_parts{ false };
|
||||||
bool m_place_on_cut_upper{ true };
|
bool m_place_on_cut_upper{ true };
|
||||||
bool m_place_on_cut_lower{ false };
|
bool m_place_on_cut_lower{ false };
|
||||||
bool m_rotate_upper{ false };
|
bool m_rotate_upper{ false };
|
||||||
@ -121,6 +131,7 @@ class GLGizmoCut3D : public GLGizmoBase
|
|||||||
GLSelectionRectangle m_selection_rectangle;
|
GLSelectionRectangle m_selection_rectangle;
|
||||||
|
|
||||||
bool m_has_invalid_connector{ false };
|
bool m_has_invalid_connector{ false };
|
||||||
|
bool m_was_cut_plane_dragged { false };
|
||||||
|
|
||||||
bool m_show_shortcuts{ false };
|
bool m_show_shortcuts{ false };
|
||||||
std::vector<std::pair<wxString, wxString>> m_shortcuts;
|
std::vector<std::pair<wxString, wxString>> m_shortcuts;
|
||||||
@ -154,6 +165,8 @@ class GLGizmoCut3D : public GLGizmoBase
|
|||||||
|
|
||||||
std::vector<std::string> m_axis_names;
|
std::vector<std::string> m_axis_names;
|
||||||
|
|
||||||
|
std::map<std::string, wxString> m_part_orientation_names;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||||
|
|
||||||
@ -192,7 +205,7 @@ protected:
|
|||||||
void on_set_hover_id() override;
|
void on_set_hover_id() override;
|
||||||
bool on_is_activable() const override;
|
bool on_is_activable() const override;
|
||||||
bool on_is_selectable() const override;
|
bool on_is_selectable() const override;
|
||||||
Vec3d mouse_position_in_local_plane(Axis axis, const Linef3&mouse_ray) const;
|
Vec3d mouse_position_in_local_plane(GrabberID axis, const Linef3&mouse_ray) const;
|
||||||
void dragging_grabber_z(const GLGizmoBase::UpdateData &data);
|
void dragging_grabber_z(const GLGizmoBase::UpdateData &data);
|
||||||
void dragging_grabber_xy(const GLGizmoBase::UpdateData &data);
|
void dragging_grabber_xy(const GLGizmoBase::UpdateData &data);
|
||||||
void dragging_connector(const GLGizmoBase::UpdateData &data);
|
void dragging_connector(const GLGizmoBase::UpdateData &data);
|
||||||
@ -211,6 +224,12 @@ protected:
|
|||||||
void render_build_size();
|
void render_build_size();
|
||||||
void reset_cut_plane();
|
void reset_cut_plane();
|
||||||
void set_connectors_editing(bool connectors_editing);
|
void set_connectors_editing(bool connectors_editing);
|
||||||
|
void flip_cut_plane();
|
||||||
|
void render_flip_plane_button(bool disable_pred = false);
|
||||||
|
void add_vertical_scaled_interval(float interval);
|
||||||
|
void add_horizontal_scaled_interval(float interval);
|
||||||
|
void add_horizontal_shift(float shift);
|
||||||
|
void render_color_marker(float size, const ImU32& color);
|
||||||
void render_cut_plane_input_window(CutConnectors &connectors);
|
void render_cut_plane_input_window(CutConnectors &connectors);
|
||||||
void init_input_window_data(CutConnectors &connectors);
|
void init_input_window_data(CutConnectors &connectors);
|
||||||
void render_input_window_warning() const;
|
void render_input_window_warning() const;
|
||||||
@ -258,7 +277,7 @@ private:
|
|||||||
void render_cut_plane();
|
void render_cut_plane();
|
||||||
void render_model(GLModel& model, const ColorRGBA& color, Transform3d view_model_matrix);
|
void render_model(GLModel& model, const ColorRGBA& color, Transform3d view_model_matrix);
|
||||||
void render_line(GLModel& line_model, const ColorRGBA& color, Transform3d view_model_matrix, float width);
|
void render_line(GLModel& line_model, const ColorRGBA& color, Transform3d view_model_matrix, float width);
|
||||||
void render_rotation_snapping(Axis axis, const ColorRGBA& color);
|
void render_rotation_snapping(GrabberID axis, const ColorRGBA& color);
|
||||||
void render_grabber_connection(const ColorRGBA& color, Transform3d view_matrix);
|
void render_grabber_connection(const ColorRGBA& color, Transform3d view_matrix);
|
||||||
void render_cut_plane_grabbers();
|
void render_cut_plane_grabbers();
|
||||||
void render_cut_line();
|
void render_cut_line();
|
||||||
|
@ -453,10 +453,17 @@ void ImGuiWrapper::end()
|
|||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGuiWrapper::button(const wxString &label)
|
bool ImGuiWrapper::button(const wxString &label, const wxString& tooltip)
|
||||||
{
|
{
|
||||||
auto label_utf8 = into_u8(label);
|
auto label_utf8 = into_u8(label);
|
||||||
return ImGui::Button(label_utf8.c_str());
|
const bool ret = ImGui::Button(label_utf8.c_str());
|
||||||
|
|
||||||
|
if (!tooltip.IsEmpty() && ImGui::IsItemHovered()) {
|
||||||
|
auto tooltip_utf8 = into_u8(tooltip);
|
||||||
|
ImGui::SetTooltip(tooltip_utf8.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGuiWrapper::button(const wxString& label, float width, float height)
|
bool ImGuiWrapper::button(const wxString& label, float width, float height)
|
||||||
|
@ -91,7 +91,7 @@ public:
|
|||||||
bool begin(const wxString& name, bool* close, int flags = 0);
|
bool begin(const wxString& name, bool* close, int flags = 0);
|
||||||
void end();
|
void end();
|
||||||
|
|
||||||
bool button(const wxString &label);
|
bool button(const wxString &label, const wxString& tooltip = {});
|
||||||
bool button(const wxString& label, float width, float height);
|
bool button(const wxString& label, float width, float height);
|
||||||
bool button(const wxString& label, const ImVec2 &size, bool enable); // default size = ImVec2(0.f, 0.f)
|
bool button(const wxString& label, const ImVec2 &size, bool enable); // default size = ImVec2(0.f, 0.f)
|
||||||
bool radio_button(const wxString &label, bool active);
|
bool radio_button(const wxString &label, bool active);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user