Cut WIP: Suppress un-universal scaling for cut objects
Added editing of the tolerance
This commit is contained in:
parent
003acee218
commit
0fd29dfec7
@ -713,7 +713,7 @@ ModelVolume* ModelObject::add_volume(const ModelVolume &other, ModelVolumeType t
|
|||||||
ModelVolume* v = new ModelVolume(this, other);
|
ModelVolume* v = new ModelVolume(this, other);
|
||||||
if (type != ModelVolumeType::INVALID && v->type() != type)
|
if (type != ModelVolumeType::INVALID && v->type() != type)
|
||||||
v->set_type(type);
|
v->set_type(type);
|
||||||
v->source.is_connector = other.source.is_connector;
|
v->cut_info = other.cut_info;
|
||||||
this->volumes.push_back(v);
|
this->volumes.push_back(v);
|
||||||
// The volume should already be centered at this point of time when copying shared pointers of the triangle mesh and convex hull.
|
// The volume should already be centered at this point of time when copying shared pointers of the triangle mesh and convex hull.
|
||||||
// v->center_geometry_after_creation();
|
// v->center_geometry_after_creation();
|
||||||
@ -1380,10 +1380,9 @@ indexed_triangle_set ModelObject::get_connector_mesh(CutConnectorAttributes conn
|
|||||||
|
|
||||||
void ModelObject::apply_cut_connectors(const std::string& name, CutConnectorAttributes connector_attributes)
|
void ModelObject::apply_cut_connectors(const std::string& name, CutConnectorAttributes connector_attributes)
|
||||||
{
|
{
|
||||||
// discard old connector markers vor volumes
|
// discard old connector markers for volumes
|
||||||
for (ModelVolume* volume : volumes) {
|
for (ModelVolume* volume : volumes)
|
||||||
volume->source.is_connector = false;
|
volume->cut_info.discard();
|
||||||
}
|
|
||||||
|
|
||||||
if (cut_connectors.empty())
|
if (cut_connectors.empty())
|
||||||
return;
|
return;
|
||||||
@ -1404,8 +1403,8 @@ void ModelObject::apply_cut_connectors(const std::string& name, CutConnectorAttr
|
|||||||
Vec3d::Ones()
|
Vec3d::Ones()
|
||||||
));
|
));
|
||||||
|
|
||||||
|
new_volume->cut_info = { true, connector.radius_tolerance, connector.height_tolerance };
|
||||||
new_volume->name = name + "-" + std::to_string(++connector_id);
|
new_volume->name = name + "-" + std::to_string(++connector_id);
|
||||||
new_volume->source.is_connector = true;
|
|
||||||
}
|
}
|
||||||
cut_id.increase_connectors_cnt(cut_connectors.size());
|
cut_id.increase_connectors_cnt(cut_connectors.size());
|
||||||
|
|
||||||
@ -1481,27 +1480,47 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
|||||||
dowels->input_file.clear();
|
dowels->input_file.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using namespace Geometry;
|
||||||
|
|
||||||
// Because transformations are going to be applied to meshes directly,
|
// Because transformations are going to be applied to meshes directly,
|
||||||
// we reset transformation of all instances and volumes,
|
// we reset transformation of all instances and volumes,
|
||||||
// except for translation and Z-rotation on instances, which are preserved
|
// except for translation and Z-rotation on instances, which are preserved
|
||||||
// in the transformation matrix and not applied to the mesh transform.
|
// in the transformation matrix and not applied to the mesh transform.
|
||||||
|
|
||||||
// const auto instance_matrix = instances[instance]->get_matrix(true);
|
// const auto instance_matrix = instances[instance]->get_matrix(true);
|
||||||
const auto instance_matrix = Geometry::assemble_transform(
|
const auto instance_matrix = assemble_transform(
|
||||||
Vec3d::Zero(), // don't apply offset
|
Vec3d::Zero(), // don't apply offset
|
||||||
instances[instance]->get_rotation().cwiseProduct(Vec3d(1.0, 1.0, 1.0)),
|
instances[instance]->get_rotation().cwiseProduct(Vec3d(1.0, 1.0, 1.0)),
|
||||||
instances[instance]->get_scaling_factor(),
|
instances[instance]->get_scaling_factor(),
|
||||||
instances[instance]->get_mirror()
|
instances[instance]->get_mirror()
|
||||||
);
|
);
|
||||||
|
|
||||||
const auto cut_matrix = Geometry::assemble_transform(-cut_center);
|
const auto cut_matrix = rotation_transform(cut_rotation).inverse() * assemble_transform(-cut_center);
|
||||||
|
const auto invert_cut_matrix = assemble_transform(cut_center, cut_rotation);
|
||||||
const auto invert_cut_matrix = Geometry::assemble_transform(cut_center, cut_rotation);
|
|
||||||
|
|
||||||
// Displacement (in instance coordinates) to be applied to place the upper parts
|
// Displacement (in instance coordinates) to be applied to place the upper parts
|
||||||
Vec3d local_displace = Vec3d::Zero();
|
Vec3d local_displace = Vec3d::Zero();
|
||||||
Vec3d local_dowels_displace = Vec3d::Zero();
|
Vec3d local_dowels_displace = Vec3d::Zero();
|
||||||
|
|
||||||
|
Vec3d rotate_z180 = deg2rad(180.0) * Vec3d::UnitX();
|
||||||
|
|
||||||
|
auto apply_tolerance = [](ModelVolume * vol)
|
||||||
|
{
|
||||||
|
Vec3d sf = vol->get_scaling_factor();
|
||||||
|
/*
|
||||||
|
// correct Z offset in respect to the new size
|
||||||
|
Vec3d pos = vol->get_offset();
|
||||||
|
pos[Z] += sf[Z] * 0.5 * vol->cut_info.height_tolerance;
|
||||||
|
vol->set_offset(pos);
|
||||||
|
*/
|
||||||
|
// make a "hole" wider
|
||||||
|
sf[X] *= (1 + vol->cut_info.radius_tolerance);
|
||||||
|
sf[Y] *= (1 + vol->cut_info.radius_tolerance);
|
||||||
|
// make a "hole" dipper
|
||||||
|
sf[Z] *= (1 + vol->cut_info.height_tolerance);
|
||||||
|
vol->set_scaling_factor(sf);
|
||||||
|
};
|
||||||
|
|
||||||
for (ModelVolume* volume : volumes) {
|
for (ModelVolume* volume : volumes) {
|
||||||
const auto volume_matrix = volume->get_matrix();
|
const auto volume_matrix = volume->get_matrix();
|
||||||
|
|
||||||
@ -1510,43 +1529,33 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
|||||||
volume->mmu_segmentation_facets.reset();
|
volume->mmu_segmentation_facets.reset();
|
||||||
|
|
||||||
if (!volume->is_model_part()) {
|
if (!volume->is_model_part()) {
|
||||||
if (volume->source.is_connector) {
|
if (volume->cut_info.is_connector) {
|
||||||
|
// ! Don't apply instance transformation for the conntectors.
|
||||||
|
// This transformation is already there
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper)) {
|
if (attributes.has(ModelObjectCutAttribute::KeepUpper)) {
|
||||||
|
|
||||||
Transform3d m = attributes.has(ModelObjectCutAttribute::PlaceOnCutUpper) ?
|
|
||||||
Geometry::rotation_transform(cut_rotation).inverse() * cut_matrix * instance_matrix * volume_matrix :
|
|
||||||
instance_matrix * volume_matrix;
|
|
||||||
volume->set_transformation(m);
|
|
||||||
|
|
||||||
ModelVolume* vol = upper->add_volume(*volume);
|
ModelVolume* vol = upper->add_volume(*volume);
|
||||||
// make a "hole" dipper
|
vol->set_transformation(volume_matrix);
|
||||||
vol->set_scaling_factor(Z, 1.1 * vol->get_scaling_factor(Z));
|
apply_tolerance(vol);
|
||||||
}
|
}
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepLower)) {
|
if (attributes.has(ModelObjectCutAttribute::KeepLower)) {
|
||||||
|
|
||||||
Transform3d m = attributes.has(ModelObjectCutAttribute::PlaceOnCutLower) ?
|
|
||||||
Geometry::rotation_transform(Geometry::deg2rad(180.0) * Vec3d::UnitX()) * Geometry::rotation_transform(cut_rotation).inverse() * cut_matrix * instance_matrix * volume_matrix :
|
|
||||||
instance_matrix * volume_matrix;
|
|
||||||
volume->set_transformation(m);
|
|
||||||
ModelVolume* vol = lower->add_volume(*volume);
|
ModelVolume* vol = lower->add_volume(*volume);
|
||||||
|
vol->set_transformation(volume_matrix);
|
||||||
|
|
||||||
if (attributes.has(ModelObjectCutAttribute::CreateDowels))
|
if (attributes.has(ModelObjectCutAttribute::CreateDowels))
|
||||||
// make a "hole" dipper
|
apply_tolerance(vol);
|
||||||
vol->set_scaling_factor(Z, 1.2 * vol->get_scaling_factor(Z));
|
|
||||||
else
|
else
|
||||||
// for lower part change type of connector from NEGATIVE_VOLUME to MODEL_PART if this connector is a plug
|
// for lower part change type of connector from NEGATIVE_VOLUME to MODEL_PART if this connector is a plug
|
||||||
vol->set_type(ModelVolumeType::MODEL_PART);
|
vol->set_type(ModelVolumeType::MODEL_PART);
|
||||||
}
|
}
|
||||||
if (attributes.has(ModelObjectCutAttribute::CreateDowels)) {
|
if (attributes.has(ModelObjectCutAttribute::CreateDowels)) {
|
||||||
// add one more solid part same as connector if this connector is a dowel
|
// add one more solid part same as connector if this connector is a dowel
|
||||||
// But discard rotation and Z-offset for this volume
|
|
||||||
volume->set_rotation(Vec3d::Zero());
|
|
||||||
Vec3d offset = volume->get_offset();
|
|
||||||
offset[Z] = 0.0;
|
|
||||||
volume->set_offset(offset);
|
|
||||||
|
|
||||||
ModelVolume* vol = dowels->add_volume(*volume);
|
ModelVolume* vol = dowels->add_volume(*volume);
|
||||||
vol->set_type(ModelVolumeType::MODEL_PART);
|
vol->set_type(ModelVolumeType::MODEL_PART);
|
||||||
|
|
||||||
|
// But discard rotation and Z-offset for this volume
|
||||||
|
vol->set_rotation(Vec3d::Zero());
|
||||||
|
vol->set_offset(Z, 0.0);
|
||||||
|
|
||||||
// Compute the displacement (in instance coordinates) to be applied to place the dowels
|
// Compute the displacement (in instance coordinates) to be applied to place the dowels
|
||||||
local_dowels_displace = lower->full_raw_mesh_bounding_box().size().cwiseProduct(Vec3d(1.0, 1.0, 0.0));
|
local_dowels_displace = lower->full_raw_mesh_bounding_box().size().cwiseProduct(Vec3d(1.0, 1.0, 0.0));
|
||||||
}
|
}
|
||||||
@ -1556,19 +1565,18 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
|||||||
// to the modifier volume transformation to preserve their shape properly.
|
// to the modifier volume transformation to preserve their shape properly.
|
||||||
volume->set_transformation(Geometry::Transformation(instance_matrix * volume_matrix));
|
volume->set_transformation(Geometry::Transformation(instance_matrix * volume_matrix));
|
||||||
|
|
||||||
|
// #ysFIXME - add logic for the negative volumes/connectors
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper))
|
if (attributes.has(ModelObjectCutAttribute::KeepUpper))
|
||||||
upper->add_volume(*volume);
|
upper->add_volume(*volume);
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepLower))
|
if (attributes.has(ModelObjectCutAttribute::KeepLower))
|
||||||
lower->add_volume(*volume);
|
lower->add_volume(*volume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!volume->mesh().empty()
|
else if (!volume->mesh().empty()) {
|
||||||
// && !volume->source.is_connector // we don't allow to cut a connectors
|
|
||||||
) {
|
|
||||||
// Transform the mesh by the combined transformation matrix.
|
// Transform the mesh by the combined transformation matrix.
|
||||||
// Flip the triangles in case the composite transformation is left handed.
|
// Flip the triangles in case the composite transformation is left handed.
|
||||||
TriangleMesh mesh(volume->mesh());
|
TriangleMesh mesh(volume->mesh());
|
||||||
mesh.transform(Geometry::rotation_transform(cut_rotation).inverse() * cut_matrix * instance_matrix * volume_matrix, true);
|
mesh.transform(cut_matrix * instance_matrix* volume_matrix, true);
|
||||||
|
|
||||||
volume->reset_mesh();
|
volume->reset_mesh();
|
||||||
// Reset volume transformation except for offset
|
// Reset volume transformation except for offset
|
||||||
@ -1588,8 +1596,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepUpper) && !upper_mesh.empty()) {
|
if (attributes.has(ModelObjectCutAttribute::KeepUpper) && !upper_mesh.empty()) {
|
||||||
if (!attributes.has(ModelObjectCutAttribute::PlaceOnCutUpper))
|
upper_mesh.transform(invert_cut_matrix);
|
||||||
upper_mesh.transform(invert_cut_matrix);
|
|
||||||
|
|
||||||
ModelVolume* vol = upper->add_volume(upper_mesh);
|
ModelVolume* vol = upper->add_volume(upper_mesh);
|
||||||
vol->name = volume->name;
|
vol->name = volume->name;
|
||||||
@ -1600,10 +1607,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
|||||||
vol->set_material(volume->material_id(), *volume->material());
|
vol->set_material(volume->material_id(), *volume->material());
|
||||||
}
|
}
|
||||||
if (attributes.has(ModelObjectCutAttribute::KeepLower) && !lower_mesh.empty()) {
|
if (attributes.has(ModelObjectCutAttribute::KeepLower) && !lower_mesh.empty()) {
|
||||||
if (attributes.has(ModelObjectCutAttribute::PlaceOnCutLower))
|
lower_mesh.transform(invert_cut_matrix);
|
||||||
lower_mesh.transform(Geometry::assemble_transform(Vec3d::Zero(), Geometry::deg2rad(180.0)*Vec3d::UnitX()));
|
|
||||||
else
|
|
||||||
lower_mesh.transform(invert_cut_matrix);
|
|
||||||
|
|
||||||
ModelVolume* vol = lower->add_volume(lower_mesh);
|
ModelVolume* vol = lower->add_volume(lower_mesh);
|
||||||
vol->name = volume->name;
|
vol->name = volume->name;
|
||||||
@ -1643,7 +1647,22 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
|||||||
|
|
||||||
obj_instance->set_transformation(Geometry::Transformation());
|
obj_instance->set_transformation(Geometry::Transformation());
|
||||||
obj_instance->set_offset(offset + displace);
|
obj_instance->set_offset(offset + displace);
|
||||||
obj_instance->set_rotation(Vec3d(attributes.has(ModelObjectCutAttribute::FlipUpper) ? Geometry::deg2rad(180.0) : 0.0, 0.0, i == instance ? 0.0 : rot_z));
|
|
||||||
|
Vec3d rotation = Vec3d::Zero();
|
||||||
|
if (attributes.has(ModelObjectCutAttribute::PlaceOnCutUpper)) {
|
||||||
|
Transform3d trafo = rotation_transform(cut_rotation).inverse();
|
||||||
|
if (i != instance)
|
||||||
|
trafo = rotation_transform(rot_z * Vec3d::UnitZ()) * trafo;
|
||||||
|
rotation = Transformation(trafo).get_rotation();
|
||||||
|
}
|
||||||
|
else if (attributes.has(ModelObjectCutAttribute::FlipUpper)) {
|
||||||
|
rotation = rotate_z180;
|
||||||
|
if (i != instance)
|
||||||
|
rotation[Z] = rot_z;
|
||||||
|
}
|
||||||
|
else if (i != instance)
|
||||||
|
rotation[Z] = rot_z/* * Vec3d::UnitZ()*/;
|
||||||
|
obj_instance->set_rotation(rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.push_back(upper);
|
res.push_back(upper);
|
||||||
@ -1666,7 +1685,22 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Vec3d& cut_center, const
|
|||||||
const double rot_z = obj_instance->get_rotation().z();
|
const double rot_z = obj_instance->get_rotation().z();
|
||||||
obj_instance->set_transformation(Geometry::Transformation());
|
obj_instance->set_transformation(Geometry::Transformation());
|
||||||
obj_instance->set_offset(offset);
|
obj_instance->set_offset(offset);
|
||||||
obj_instance->set_rotation(Vec3d(attributes.has(ModelObjectCutAttribute::FlipLower) ? Geometry::deg2rad(180.0) : 0.0, 0.0, i == instance ? 0.0 : rot_z));
|
|
||||||
|
Vec3d rotation = Vec3d::Zero();
|
||||||
|
if (attributes.has(ModelObjectCutAttribute::PlaceOnCutLower)) {
|
||||||
|
Transform3d trafo = rotation_transform(rotate_z180) * rotation_transform(cut_rotation).inverse();
|
||||||
|
if (i != instance)
|
||||||
|
trafo = rotation_transform(rot_z * Vec3d::UnitZ()) * trafo;
|
||||||
|
rotation = Transformation(trafo).get_rotation();
|
||||||
|
}
|
||||||
|
else if (attributes.has(ModelObjectCutAttribute::FlipLower)) {
|
||||||
|
rotation = rotate_z180;
|
||||||
|
if (i != instance)
|
||||||
|
rotation[Z] = rot_z;
|
||||||
|
}
|
||||||
|
else if (i != instance)
|
||||||
|
rotation[Z] = rot_z;
|
||||||
|
obj_instance->set_rotation(rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.push_back(lower);
|
res.push_back(lower);
|
||||||
|
@ -225,18 +225,20 @@ struct CutConnector
|
|||||||
Vec3d rotation;
|
Vec3d rotation;
|
||||||
float radius;
|
float radius;
|
||||||
float height;
|
float height;
|
||||||
|
float radius_tolerance;// [0.f : 1.f]
|
||||||
|
float height_tolerance;// [0.f : 1.f]
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
|
|
||||||
CutConnector()
|
CutConnector()
|
||||||
: pos(Vec3d::Zero()), rotation(Vec3d::UnitZ()), radius(5.f), height(10.f)
|
: pos(Vec3d::Zero()), rotation(Vec3d::UnitZ()), radius(5.f), height(10.f), radius_tolerance(0.f), height_tolerance(0.1f)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CutConnector(Vec3d p, Vec3d rot, float r, float h, bool fl = false)
|
CutConnector(Vec3d p, Vec3d rot, float r, float h, float rt, float ht, bool fl = false)
|
||||||
: pos(p), rotation(rot), radius(r), height(h), failed(fl)
|
: pos(p), rotation(rot), radius(r), height(h), radius_tolerance(rt), height_tolerance(ht), failed(fl)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CutConnector(const CutConnector& rhs) :
|
CutConnector(const CutConnector& rhs) :
|
||||||
CutConnector(rhs.pos, rhs.rotation, rhs.radius, rhs.height, rhs.failed) {}
|
CutConnector(rhs.pos, rhs.rotation, rhs.radius, rhs.height, rhs.radius_tolerance, rhs.height_tolerance, rhs.failed) {}
|
||||||
|
|
||||||
bool operator==(const CutConnector& sp) const;
|
bool operator==(const CutConnector& sp) const;
|
||||||
|
|
||||||
@ -251,7 +253,7 @@ struct CutConnector
|
|||||||
*/
|
*/
|
||||||
template<class Archive> inline void serialize(Archive& ar)
|
template<class Archive> inline void serialize(Archive& ar)
|
||||||
{
|
{
|
||||||
ar(pos, rotation, radius, height, failed);
|
ar(pos, rotation, radius, height, radius_tolerance, height_tolerance, failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr size_t steps = 32;
|
static constexpr size_t steps = 32;
|
||||||
@ -696,16 +698,25 @@ public:
|
|||||||
bool is_converted_from_meters{ false };
|
bool is_converted_from_meters{ false };
|
||||||
bool is_from_builtin_objects{ false };
|
bool is_from_builtin_objects{ false };
|
||||||
|
|
||||||
bool is_connector{ false };
|
|
||||||
|
|
||||||
template<class Archive> void serialize(Archive& ar) {
|
template<class Archive> void serialize(Archive& ar) {
|
||||||
//FIXME Vojtech: Serialize / deserialize only if the Source is set.
|
//FIXME Vojtech: Serialize / deserialize only if the Source is set.
|
||||||
// likely testing input_file or object_idx would be sufficient.
|
// likely testing input_file or object_idx would be sufficient.
|
||||||
ar(input_file, object_idx, volume_idx, mesh_offset, transform, is_converted_from_inches, is_converted_from_meters, is_from_builtin_objects, is_connector);
|
ar(input_file, object_idx, volume_idx, mesh_offset, transform, is_converted_from_inches, is_converted_from_meters, is_from_builtin_objects);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Source source;
|
Source source;
|
||||||
|
|
||||||
|
// struct used by cut command
|
||||||
|
// It contains information about connetors
|
||||||
|
struct CutInfo
|
||||||
|
{
|
||||||
|
bool is_connector {false};
|
||||||
|
float radius_tolerance;// [0.f : 1.f]
|
||||||
|
float height_tolerance;// [0.f : 1.f]
|
||||||
|
|
||||||
|
void discard() { is_connector = false; }
|
||||||
|
} cut_info;
|
||||||
|
|
||||||
// The triangular model.
|
// The triangular model.
|
||||||
const TriangleMesh& mesh() const { return *m_mesh.get(); }
|
const TriangleMesh& mesh() const { return *m_mesh.get(); }
|
||||||
void set_mesh(const TriangleMesh &mesh) { m_mesh = std::make_shared<const TriangleMesh>(mesh); }
|
void set_mesh(const TriangleMesh &mesh) { m_mesh = std::make_shared<const TriangleMesh>(mesh); }
|
||||||
|
@ -2499,6 +2499,7 @@ void ObjectList::part_selection_changed()
|
|||||||
|
|
||||||
bool enable_manipulation {true};
|
bool enable_manipulation {true};
|
||||||
bool disable_ss_manipulation {false};
|
bool disable_ss_manipulation {false};
|
||||||
|
bool disable_ununiform_scale {false};
|
||||||
|
|
||||||
const auto item = GetSelection();
|
const auto item = GetSelection();
|
||||||
|
|
||||||
@ -2543,6 +2544,7 @@ void ObjectList::part_selection_changed()
|
|||||||
disable_ss_manipulation = true;
|
disable_ss_manipulation = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
disable_ununiform_scale = !cut_objects.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2649,8 +2651,11 @@ void ObjectList::part_selection_changed()
|
|||||||
|
|
||||||
if (disable_ss_manipulation)
|
if (disable_ss_manipulation)
|
||||||
wxGetApp().obj_manipul()->DisableScale();
|
wxGetApp().obj_manipul()->DisableScale();
|
||||||
else
|
else {
|
||||||
wxGetApp().obj_manipul()->Enable(enable_manipulation);
|
wxGetApp().obj_manipul()->Enable(enable_manipulation);
|
||||||
|
if (disable_ununiform_scale)
|
||||||
|
wxGetApp().obj_manipul()->DisableUnuniformScale();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_and_show_settings)
|
if (update_and_show_settings)
|
||||||
|
@ -580,7 +580,11 @@ void ObjectManipulation::Enable(const bool enadle)
|
|||||||
{
|
{
|
||||||
for (auto editor : m_editors)
|
for (auto editor : m_editors)
|
||||||
editor->Enable(enadle);
|
editor->Enable(enadle);
|
||||||
for (wxWindow* win : std::initializer_list<wxWindow*>{ m_reset_scale_button, m_reset_rotation_button, m_drop_to_bed_button, m_check_inch, m_lock_bnt })
|
for (wxWindow* win : std::initializer_list<wxWindow*>{ m_reset_scale_button, m_reset_rotation_button, m_drop_to_bed_button, m_check_inch, m_lock_bnt
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
,m_reset_skew_button
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
})
|
||||||
win->Enable(enadle);
|
win->Enable(enadle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,10 +592,19 @@ void ObjectManipulation::DisableScale()
|
|||||||
{
|
{
|
||||||
for (auto editor : m_editors)
|
for (auto editor : m_editors)
|
||||||
editor->Enable(editor->has_opt_key("scale") || editor->has_opt_key("size") ? false : true);
|
editor->Enable(editor->has_opt_key("scale") || editor->has_opt_key("size") ? false : true);
|
||||||
for (wxWindow* win : std::initializer_list<wxWindow*>{ m_reset_scale_button, m_lock_bnt })
|
for (wxWindow* win : std::initializer_list<wxWindow*>{ m_reset_scale_button, m_lock_bnt
|
||||||
|
#if ENABLE_WORLD_COORDINATE
|
||||||
|
,m_reset_skew_button
|
||||||
|
#endif // ENABLE_WORLD_COORDINATE
|
||||||
|
})
|
||||||
win->Enable(false);
|
win->Enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjectManipulation::DisableUnuniformScale()
|
||||||
|
{
|
||||||
|
m_lock_bnt->disable();
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectManipulation::update_ui_from_settings()
|
void ObjectManipulation::update_ui_from_settings()
|
||||||
{
|
{
|
||||||
if (m_imperial_units != (wxGetApp().app_config->get("use_inches") == "1")) {
|
if (m_imperial_units != (wxGetApp().app_config->get("use_inches") == "1")) {
|
||||||
|
@ -201,6 +201,7 @@ public:
|
|||||||
void Enable(const bool enadle = true);
|
void Enable(const bool enadle = true);
|
||||||
void Disable() { Enable(false); }
|
void Disable() { Enable(false); }
|
||||||
void DisableScale();
|
void DisableScale();
|
||||||
|
void DisableUnuniformScale();
|
||||||
void update_ui_from_settings();
|
void update_ui_from_settings();
|
||||||
bool use_colors() { return m_use_colors; }
|
bool use_colors() { return m_use_colors; }
|
||||||
|
|
||||||
|
@ -430,12 +430,12 @@ bool GLGizmoCut3D::render_double_input(const std::string& label, double& value_i
|
|||||||
return old_val != value;
|
return old_val != value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoCut3D::render_slicer_double_input(const std::string& label, double& value_in)
|
bool GLGizmoCut3D::render_slider_double_input(const std::string& label, double& value_in, int& tolerance_in)
|
||||||
{
|
{
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
m_imgui->text(label);
|
m_imgui->text(label);
|
||||||
ImGui::SameLine(m_label_width);
|
ImGui::SameLine(m_label_width);
|
||||||
ImGui::PushItemWidth(m_control_width);
|
ImGui::PushItemWidth(m_control_width * 0.85f);
|
||||||
|
|
||||||
float value = (float)value_in;
|
float value = (float)value_in;
|
||||||
if (m_imperial_units)
|
if (m_imperial_units)
|
||||||
@ -443,15 +443,25 @@ bool GLGizmoCut3D::render_slicer_double_input(const std::string& label, double&
|
|||||||
float old_val = value;
|
float old_val = value;
|
||||||
|
|
||||||
const BoundingBoxf3 bbox = bounding_box();
|
const BoundingBoxf3 bbox = bounding_box();
|
||||||
const float mean_size = float((bbox.size().x() + bbox.size().y() + bbox.size().z()) / 9.0);
|
float mean_size = float((bbox.size().x() + bbox.size().y() + bbox.size().z()) / 9.0);
|
||||||
|
float min_size = 1.f;
|
||||||
m_imgui->slider_float(("##" + label).c_str(), &value, 1.0f, mean_size);
|
if (m_imperial_units) {
|
||||||
|
mean_size *= ObjectManipulation::mm_to_in;
|
||||||
ImGui::SameLine();
|
min_size *= ObjectManipulation::mm_to_in;
|
||||||
m_imgui->text(m_imperial_units ? _L("in") : _L("mm"));
|
}
|
||||||
|
std::string format = m_imperial_units ? "%.4f " + _u8L("in") : "%.2f " + _u8L("mm");
|
||||||
|
|
||||||
|
m_imgui->slider_float(("##" + label).c_str(), &value, min_size, mean_size, format.c_str());
|
||||||
value_in = (double)(value * (m_imperial_units ? ObjectManipulation::in_to_mm : 1.0));
|
value_in = (double)(value * (m_imperial_units ? ObjectManipulation::in_to_mm : 1.0));
|
||||||
return old_val != value;
|
|
||||||
|
ImGui::SameLine(m_label_width + m_control_width + 3);
|
||||||
|
ImGui::PushItemWidth(m_control_width * 0.3f);
|
||||||
|
|
||||||
|
float old_tolerance, tolerance = old_tolerance = (float)tolerance_in;
|
||||||
|
m_imgui->slider_float(("##tolerance_" + label).c_str(), &tolerance, 1.f, 20.f, "%.f %%", 1.f, true, _L("Tolerance"));
|
||||||
|
tolerance_in = (int)tolerance;
|
||||||
|
|
||||||
|
return old_val != value || old_tolerance != tolerance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoCut3D::render_move_center_input(int axis)
|
void GLGizmoCut3D::render_move_center_input(int axis)
|
||||||
@ -1253,11 +1263,11 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
|
|||||||
if (m_imgui->button(" " + _L("Reset") + " ##connectors"))
|
if (m_imgui->button(" " + _L("Reset") + " ##connectors"))
|
||||||
reset_connectors();
|
reset_connectors();
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
/*
|
||||||
m_imgui->text(_L("Mode"));
|
m_imgui->text(_L("Mode"));
|
||||||
render_connect_mode_radio_button(CutConnectorMode::Auto);
|
render_connect_mode_radio_button(CutConnectorMode::Auto);
|
||||||
render_connect_mode_radio_button(CutConnectorMode::Manual);
|
render_connect_mode_radio_button(CutConnectorMode::Manual);
|
||||||
|
*/
|
||||||
m_imgui->text(_L("Type"));
|
m_imgui->text(_L("Type"));
|
||||||
render_connect_type_radio_button(CutConnectorType::Plug);
|
render_connect_type_radio_button(CutConnectorType::Plug);
|
||||||
render_connect_type_radio_button(CutConnectorType::Dowel);
|
render_connect_type_radio_button(CutConnectorType::Dowel);
|
||||||
@ -1267,12 +1277,16 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
|
|||||||
if (render_combo(_u8L("Shape"), m_connector_shapes, m_connector_shape_id))
|
if (render_combo(_u8L("Shape"), m_connector_shapes, m_connector_shape_id))
|
||||||
update_connector_shape();
|
update_connector_shape();
|
||||||
|
|
||||||
if (render_slicer_double_input(_u8L("Depth ratio"), m_connector_depth_ratio))
|
if (render_slider_double_input(_u8L("Depth ratio"), m_connector_depth_ratio, m_connector_depth_ratio_tolerance))
|
||||||
for (auto& connector : connectors)
|
for (auto& connector : connectors) {
|
||||||
connector.height = float(m_connector_depth_ratio);
|
connector.height = float(m_connector_depth_ratio);
|
||||||
if (render_slicer_double_input(_u8L("Size"), m_connector_size))
|
connector.height_tolerance = 0.01f * m_connector_depth_ratio;
|
||||||
for (auto& connector : connectors)
|
}
|
||||||
|
if (render_slider_double_input(_u8L("Size"), m_connector_size, m_connector_size_tolerance))
|
||||||
|
for (auto& connector : connectors) {
|
||||||
connector.radius = float(m_connector_size * 0.5);
|
connector.radius = float(m_connector_size * 0.5);
|
||||||
|
connector.radius_tolerance = 0.01f * m_connector_size_tolerance;
|
||||||
|
}
|
||||||
|
|
||||||
m_imgui->disabled_end();
|
m_imgui->disabled_end();
|
||||||
|
|
||||||
@ -1710,7 +1724,9 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi
|
|||||||
//std::cout << hit.x() << "\t" << hit.y() << "\t" << hit.z() << std::endl;
|
//std::cout << hit.x() << "\t" << hit.y() << "\t" << hit.z() << std::endl;
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Add connector"), UndoRedo::SnapshotType::GizmoAction);
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Add connector"), UndoRedo::SnapshotType::GizmoAction);
|
||||||
|
|
||||||
connectors.emplace_back(hit, Geometry::Transformation(m_rotation_m).get_rotation(), float(m_connector_size * 0.5), float(m_connector_depth_ratio));
|
connectors.emplace_back(hit, Geometry::Transformation(m_rotation_m).get_rotation(),
|
||||||
|
float(m_connector_size * 0.5), float(m_connector_depth_ratio),
|
||||||
|
float(0.01f * m_connector_size_tolerance), float(0.01f * m_connector_depth_ratio_tolerance));
|
||||||
update_model_object();
|
update_model_object();
|
||||||
m_selected.push_back(false);
|
m_selected.push_back(false);
|
||||||
assert(m_selected.size() == connectors.size());
|
assert(m_selected.size() == connectors.size());
|
||||||
|
@ -81,6 +81,9 @@ class GLGizmoCut3D : public GLGizmoBase
|
|||||||
double m_connector_depth_ratio{ 3.0 };
|
double m_connector_depth_ratio{ 3.0 };
|
||||||
double m_connector_size{ 2.5 };
|
double m_connector_size{ 2.5 };
|
||||||
|
|
||||||
|
int m_connector_depth_ratio_tolerance{ 10 };
|
||||||
|
int m_connector_size_tolerance{ 0 };
|
||||||
|
|
||||||
float m_label_width{ 150.0 };
|
float m_label_width{ 150.0 };
|
||||||
float m_control_width{ 200.0 };
|
float m_control_width{ 200.0 };
|
||||||
bool m_imperial_units{ false };
|
bool m_imperial_units{ false };
|
||||||
@ -174,7 +177,7 @@ private:
|
|||||||
void set_center(const Vec3d& center);
|
void set_center(const Vec3d& center);
|
||||||
bool render_combo(const std::string& label, const std::vector<std::string>& lines, size_t& selection_idx);
|
bool render_combo(const std::string& label, const std::vector<std::string>& lines, size_t& selection_idx);
|
||||||
bool render_double_input(const std::string& label, double& value_in);
|
bool render_double_input(const std::string& label, double& value_in);
|
||||||
bool render_slicer_double_input(const std::string& label, double& value_in);
|
bool render_slider_double_input(const std::string& label, double& value_in, int& tolerance_in);
|
||||||
void render_move_center_input(int axis);
|
void render_move_center_input(int axis);
|
||||||
void render_connect_mode_radio_button(CutConnectorMode mode);
|
void render_connect_mode_radio_button(CutConnectorMode mode);
|
||||||
bool render_revert_button(const std::string& label);
|
bool render_revert_button(const std::string& label);
|
||||||
|
Loading…
Reference in New Issue
Block a user