mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 09:17:52 -06:00
Port coordinate system selection for Move, Scale and Rotate gizmo (#9099)
* NEW:add move and rotate gizmo in assemble view Cherry-picked from bambulab/BambuStudio@d9e47bd9a9 Co-authored-by: zhou.xu <zhou.xu@bambulab.com> * Deselect other parts if Alt is pressed when selecting Cherry-picked from bambulab/BambuStudio@f5eb2899e7 Co-authored-by: zhou.xu <zhou.xu@bambulab.com> * FIX:z offset is error after copy and paste several objects jira: STUDIO-6753 STUDIO-7135 Change-Id: I6d9c8eb0c957ff1e3194709704ceb6c3920baa4f (cherry picked from commit 847a7141a6f47e409566b19e73c0ebdeb08f39e2) (cherry picked from commit a5cc52beb7eef5848368e660ca4f14e95ad5f7d5) * FIX:arrow direction in scaling tool is incorrect Jira: STUDIO-5672 Change-Id: I82c0ab336805e34c8380f93e64d3b9dbbf283805 (cherry picked from commit f6f27b700f0305854fcdbcb1191af25a4b8bdbe4) * FIX:world cs is displayed incorrectly The value of world coordinate system for model_volume is displayed incorrectly Jira: STUDIO-6399 code is from PrusaSlicer thanks for PrusaSlicer and enricoturri1966 commit 325709c5ae9b937867b36103a41d12a102c99292 Author: enricoturri1966 <enricoturri@seznam.cz> Date: Thu Jan 26 15:49:00 2023 +0100 SPE-1419 - Fixed reset skew resetting mirror, reset scale resetting mirror, changed labels in Object Manipulator panel, scale of instances using the Object Manipulator panel always made as absolute Change-Id: I30fdd39effd73b8dc027e4263fa7e64937b84326 Cherry-picked from bambulab/BambuStudio@0b46b9848b Co-authored-by: enricoturri1966 <enricoturri@seznam.cz> * FIX:fix scale problem add tool tip for move,rotate,scale gizmo Jira: STUDIO-6425 STUDIO-6419 Change-Id: I0b89c9b70f83cde21c6a407bcecd78c925515cfa Cherry-picked from bambulab/BambuStudio@6dad59102b Co-authored-by: zhou.xu <zhou.xu@bambulab.com> * NEW:add Object coordinates in move gizmo jira: none Part of the code references PrusaSlicer,thanks for PrusaSlicer and enricoturri1966 commit c12eeee12f9e2c91a9dfe7905f1370143805f038 Author: enricoturri1966 <enricoturri@seznam.cz> Date: Mon Oct 2 14:26:36 2023 +0200 SPE-1926: Tech ENABLE_CGAL_BOUNDING_SPHERE - Use selection's bounding sphere center as pivot for rotations Change-Id: Iae7e4539c198af3ff1aa99e1c0ce015fbcf80256 (cherry picked from commit 2b73bc915ee27218c9803ba0a01b0d3e47adf1da) Cherry-picked from bambulab/BambuStudio@98cce3b656 Co-authored-by: enricoturri1966 <enricoturri@seznam.cz> Co-authored-by: zhou.xu <zhou.xu@bambulab.com> * FIX:fix imgui style at Object coordinate in move tool jira:STUDIO-7141 Change-Id: Ib2900012c28878c4e7ad97eb0cf319f693cb9f6f (cherry picked from commit b7b09c82897678c4f3615713bc5d1cc7a3b17b19) (cherry picked from commit c89732a04619a6d910b723c126515bae802f7167) * ENH:use local cs for non_model_part better jira: STUDIO-7234 Change-Id: I0f0e99429e5e0b7cc4932a661eceffcff4a495f6 (cherry picked from commit b4305a3bfc9e5ae05c1785a710238a70f2dfb44a) (cherry picked from commit b28ac4f812f0024ec619c5d1b3c96e4cef4debdb) * ENH:add a cross mark for object cs jira: STUDIO-6947 Change-Id: Iaaab4f072045756ac3ba12c3f65e1c7f04ba65b8 (cherry picked from commit a2a2f49b4d94f257d36c9d17b4ec952e5dc9f0eb) Cherry-picked from bambulab/BambuStudio@8400e162a7 Co-authored-by: zhou.xu <zhou.xu@bambulab.com> * NEW:add tip button for move,rotate,scale jira: STUDIO-7273 Change-Id: I44aeecd8aaa17ec49ac1d8ff2bee5c3729c52061 (cherry picked from commit 998f33b4ce588f59cef345e327a97f6f669f6089) (cherry picked from commit f5eb2899e7252ea3ff0f8a79ef8d55c6009ebb28) * FIX:scale and size sholud >0 in scale tool jira: STUDIO-7433 Change-Id: Ibd4d00d9ca4762d002049e97a6d0819649f464db (cherry picked from commit eaaf11031ee49009af14abbd05bb4a07c88aceda) (cherry picked from commit 0d393d64b804ba7ae05454bf158de470cc74a6a6) * Fix crossmark rendering * Use combox as coord selection Cherry-picked from bambulab/BambuStudio@56f628dac1 Co-authored-by: zhou.xu <zhou.xu@bambulab.com> * NEW:add "world coordinates" scale for scale gizmo upgrade Transformation class jira:none about 75% code is from PrusaSlicer,thanks for PrusaSlicer and enricoturri1966 commit b32e9366606dce7d4f8de8db84fd902113bdbe28 Author: enricoturri1966 <enricoturri@seznam.cz> Date: Tue Mar 7 14:32:18 2023 +0100 Rework of constrained scaling Change-Id: I1248ea586e6b8f2fb6cdf3aa901ed7f525c3f111 (cherry picked from commit e10381aad1412b0c47afa340b634faa3af9d1a1f) Cherry-picked from bambulab/BambuStudio@c0536c09b4 Co-authored-by: enricoturri1966 <enricoturri@seznam.cz> Co-authored-by: zhou.xu <zhou.xu@bambulab.com> * ENH:set "Rotate (relative)" jira:none code is from PrusaSlicer,thanks for PrusaSlicer and enricoturri1966 commit 243985173e70c189ad9a86eefaaea0757d9749cb Author: enricoturri1966 <enricoturri@seznam.cz> Date: Thu May 12 14:33:41 2022 +0200 Tech ENABLE_TRANSFORMATIONS_BY_MATRICES - Allow for relative rotations Change-Id: I851939093ffb6881542fb21b434e17cc31a6dab2 (cherry picked from commit e412fa3492fa2ef59b84a84be1ede80935fb8a8d) * FIX:limit scaling ratio by grabber in scale tool jira: none Change-Id: I20a4404d4e4025ae230ab46ba8d8d3e5ffed10e3 (cherry picked from commit 97f63f167e80e859fec49666c8986f5a01f61838) * FIX:selection should be not empty when update_ui_from_settings jira: none Change-Id: I74b76733eba03d148dfd70279ec2ba65f19cc39a (cherry picked from commit f402685aee747fe5c3740b2cb80fc2a60e129918) * ENH:add "volume selection" checkbox jira: none Change-Id: I68b5f54e37ea2ab9e2b65ac84abc834060f400df (cherry picked from commit eec7de441bd40408fe688587d2834b0c42c0d66f) * FIX:add can_sequential_clearance_show_in_gizmo api jira: STUDIO-7836 Change-Id: Ie0cded272596bafee4e491e379722dcc23035dc4 (cherry picked from commit 715d2b9b7840939663e99e0ecbfcefd8ecf2904f) * FIX:select all should ban in paint,cut and so on gizmo jira: STUDIO-7872 Change-Id: Ic6496dbdd892814e1fc41625ee34ffc46f171657 (cherry picked from commit 95e8ca728553081db4ecbb3d865c8b999a6ff2fa) * FIX:add wipe tower'position in move gizmo jira: STUDIO-7861 Change-Id: I8147717bc61ba06a7e1fba45532cdadc2ba1174e (cherry picked from commit 065dddb890d3ec81643b9767397bdad72ae69ebd) * ENH:fix text coordinate system calculation jira: STUDIO-6449 Change-Id: I36214c14c348e8f52b96501cd027205819b0dabc (cherry picked from commit 44287812a0cb212f1bf6fe70e32e1075f532886d) Cherry-picked from bambulab/BambuStudio@4091f3e042 Co-authored-by: zhou.xu <zhou.xu@bambulab.com> * FIX:delete old selection.translate api jira: STUDIO-8201 code is from PrusaSlicer,thanks for PrusaSlicer and enricoturri1966 commit 88ce6ccdef5f680709ea8b676688784a7af287dd Author: enricoturri1966 <enricoturri@seznam.cz> Date: Wed May 11 10:54:42 2022 +0200 Tech ENABLE_TRANSFORMATIONS_BY_MATRICES - Change-Id: Iafe963f0f7bf9028f32a4fb4a4cc8cc609662283 Change-Id: Ibbc36c004734f35564f0028dd1e537ac926a2f1f Cherry-picked from bambulab/BambuStudio@c6d9f2685e Co-authored-by: enricoturri1966 <enricoturri@seznam.cz> Co-authored-by: zhou.xu <zhou.xu@bambulab.com> * FIX:add protection for null pointer jira: none Change-Id: I9a9231bab893f5d2afa008f65165269ae176c962 (cherry picked from commit f27a713aaf77b1109fc57b8650efa6b23081f799) * FIX:when two dir is perpendicular to each other,scale error (plane_normal.dot(ray_dir)) jira:STUDIO-8274 Change-Id: Ib3145ab75e18c832d20065d204aa41b75f73b673 (cherry picked from commit fbdc9cd580f835d1a873d08ed64baed3b3db6f9a) * ENH:add "reset real zeros" button in rotate gizmo jira: STUDIO-8291 Change-Id: Ia10e4d8a2a3a073c22a1306aeab9ffa3e7b77c2b (cherry picked from commit 738e3f004daa9082709800e4e3d0d9bbe1b7ed7e) * FIX:add "absolute rotation" in rotate gizmo jira: STUDIO-8726 Change-Id: I23deb4ab11cf24ca4f0f0c5a35a74268c34f60f6 (cherry picked from commit d26b8f9fcadf8f7709a302991e43be711560e84e) (cherry picked from commit 496d69f9d1b91c6bd84804e57a276bccf79f0cbd) * Fix tooltip button size * Fix issue that reative rotation history not cleared after gizmo closed * Show selection box in assemble view * ENH:add an tip icon for assembly view jira: STUDIO-7155 Change-Id: Ie9e4fa578c8aa5bda9ff771d82f396f8b51026bb (cherry picked from commit 515f9473347fb912a9dc8c365f1c318506096083) --------- Co-authored-by: zhou.xu <zhou.xu@bambulab.com> Co-authored-by: enricoturri1966 <enricoturri@seznam.cz> Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
parent
4b0977d306
commit
1b8f798d3b
28 changed files with 1558 additions and 730 deletions
5
resources/images/toolbar_reset_zero.svg
Normal file
5
resources/images/toolbar_reset_zero.svg
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.6457 7C10.5448 7 10.4602 6.9247 10.4433 6.82524C10.1226 4.93741 8.47917 3.5 6.5 3.5C4.29086 3.5 2.5 5.29086 2.5 7.5C2.5 9.47929 3.93759 11.1228 5.82559 11.4434C5.92506 11.4603 6.00037 11.5448 6.00037 11.6457V12.7588C6.00037 12.8763 5.89925 12.9688 5.7827 12.9536C3.08405 12.6022 1 10.2945 1 7.5C1 4.46243 3.46243 2 6.5 2C9.29433 2 11.6019 4.08386 11.9536 6.78232C11.9688 6.89888 11.8763 7 11.7587 7H10.6457Z" fill="#FF6F00"/>
|
||||||
|
<path d="M11.1649 9.76271C11.0854 9.87751 10.9156 9.87751 10.8361 9.76271L8.61993 6.5639C8.52803 6.43126 8.62296 6.25 8.78433 6.25H13.2167C13.3781 6.25 13.473 6.43126 13.3811 6.5639L11.1649 9.76271Z" fill="#FF6F00"/>
|
||||||
|
<path d="M8.38678 7.61146C8.38678 8.48963 8.22064 9.15893 7.88836 9.61938C7.56082 10.0798 7.09326 10.31 6.48566 10.31C5.87807 10.31 5.40576 10.0822 5.06873 9.6265C4.73645 9.16605 4.57031 8.49438 4.57031 7.61146C4.57031 6.72855 4.73645 6.05687 5.06873 5.59643C5.40576 5.13598 5.87807 4.90576 6.48566 4.90576C7.09326 4.90576 7.56082 5.13598 7.88836 5.59643C8.22064 6.05687 8.38678 6.72855 8.38678 7.61146ZM5.85908 7.61146C5.85908 8.14786 5.90892 8.54659 6.00861 8.80767C6.11304 9.06874 6.27206 9.19928 6.48566 9.19928C6.69453 9.19928 6.8488 9.06874 6.94848 8.80767C7.04817 8.54184 7.09801 8.14311 7.09801 7.61146C7.09801 7.07982 7.04817 6.68346 6.94848 6.42238C6.8488 6.15656 6.69453 6.02364 6.48566 6.02364C6.27206 6.02364 6.11304 6.15181 6.00861 6.40814C5.90892 6.66447 5.85908 7.06558 5.85908 7.61146Z" fill="#FF6F00"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
4
resources/images/toolbar_reset_zero_hover.svg
Normal file
4
resources/images/toolbar_reset_zero_hover.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="14" height="15" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.2937 5.6687C9.71589 3.84914 8.01293 2.53076 6.00204 2.53076C3.51563 2.53076 1.5 4.54639 1.5 7.0328C1.5 9.27369 3.13722 11.1322 5.28073 11.4774C5.38062 11.4935 5.4564 11.5783 5.4564 11.6794V12.7916C5.4564 12.9091 5.35522 13.0016 5.23861 12.9868C2.28425 12.6118 0 10.0891 0 7.0328C0 3.71797 2.68721 1.03076 6.00204 1.03076C8.84765 1.03076 11.2307 3.01105 11.8484 5.6687H13.3662C13.5275 5.6687 13.6225 5.84996 13.5306 5.9826L11.0772 9.52371C10.9977 9.63851 10.8279 9.63851 10.7484 9.52371L8.29505 5.9826C8.20315 5.84996 8.29808 5.6687 8.45945 5.6687H10.2937Z" fill="#FF6F00"/>
|
||||||
|
<path d="M7.99414 7.03451C7.99414 7.96884 7.81738 8.68095 7.46384 9.17084C7.11537 9.66073 6.6179 9.90568 5.97144 9.90568C5.32499 9.90568 4.82247 9.66326 4.46389 9.17842C4.11036 8.68852 3.93359 7.97389 3.93359 7.03451C3.93359 6.09513 4.11036 5.38049 4.46389 4.8906C4.82247 4.40071 5.32499 4.15576 5.97144 4.15576C6.6179 4.15576 7.11537 4.40071 7.46384 4.8906C7.81738 5.38049 7.99414 6.09513 7.99414 7.03451ZM5.30479 7.03451C5.30479 7.60521 5.35782 8.02944 5.46387 8.30722C5.57498 8.58499 5.74417 8.72388 5.97144 8.72388C6.19366 8.72388 6.3578 8.58499 6.46386 8.30722C6.56992 8.02439 6.62295 7.60016 6.62295 7.03451C6.62295 6.46886 6.56992 6.04715 6.46386 5.76937C6.3578 5.48655 6.19366 5.34514 5.97144 5.34514C5.74417 5.34514 5.57498 5.4815 5.46387 5.75422C5.35782 6.02695 5.30479 6.45371 5.30479 7.03451Z" fill="#FF6F00"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -478,6 +478,16 @@ Transform3d Transformation::get_rotation_matrix() const
|
||||||
return extract_rotation_matrix(m_matrix);
|
return extract_rotation_matrix(m_matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vec3d Transformation::get_rotation_by_quaternion() const
|
||||||
|
{
|
||||||
|
Matrix3d rotation_matrix = m_matrix.matrix().block(0, 0, 3, 3);
|
||||||
|
Eigen::Quaterniond quaternion(rotation_matrix);
|
||||||
|
quaternion.normalize();
|
||||||
|
Vec3d temp_rotation = quaternion.matrix().eulerAngles(2, 1, 0);
|
||||||
|
std::swap(temp_rotation(0), temp_rotation(2));
|
||||||
|
return temp_rotation;
|
||||||
|
}
|
||||||
|
|
||||||
void Transformation::set_rotation(const Vec3d& rotation)
|
void Transformation::set_rotation(const Vec3d& rotation)
|
||||||
{
|
{
|
||||||
const Vec3d offset = get_offset();
|
const Vec3d offset = get_offset();
|
||||||
|
@ -839,6 +849,17 @@ TransformationSVD::TransformationSVD(const Transform3d& trafo)
|
||||||
return curMat;
|
return curMat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Transformation generate_transform(const Vec3d& x_dir, const Vec3d& y_dir, const Vec3d& z_dir, const Vec3d& origin) {
|
||||||
|
Matrix3d m;
|
||||||
|
m.col(0) = x_dir.normalized();
|
||||||
|
m.col(1) = y_dir.normalized();
|
||||||
|
m.col(2) = z_dir.normalized();
|
||||||
|
Transform3d mm(m);
|
||||||
|
Transformation tran(mm);
|
||||||
|
tran.set_offset(origin);
|
||||||
|
return tran;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_point_inside_polygon_corner(const Point &a, const Point &b, const Point &c, const Point &query_point) {
|
bool is_point_inside_polygon_corner(const Point &a, const Point &b, const Point &c, const Point &query_point) {
|
||||||
// Cast all input points into int64_t to prevent overflows when points are close to max values of coord_t.
|
// Cast all input points into int64_t to prevent overflows when points are close to max values of coord_t.
|
||||||
const Vec2i64 a_i64 = a.cast<int64_t>();
|
const Vec2i64 a_i64 = a.cast<int64_t>();
|
||||||
|
|
|
@ -421,6 +421,7 @@ public:
|
||||||
void set_offset(Axis axis, double offset) { m_matrix.translation()[axis] = offset; }
|
void set_offset(Axis axis, double offset) { m_matrix.translation()[axis] = offset; }
|
||||||
|
|
||||||
Vec3d get_rotation() const;
|
Vec3d get_rotation() const;
|
||||||
|
Vec3d get_rotation_by_quaternion() const;
|
||||||
double get_rotation(Axis axis) const { return get_rotation()[axis]; }
|
double get_rotation(Axis axis) const { return get_rotation()[axis]; }
|
||||||
|
|
||||||
Transform3d get_rotation_matrix() const;
|
Transform3d get_rotation_matrix() const;
|
||||||
|
@ -545,6 +546,7 @@ inline bool is_rotation_ninety_degrees(const Vec3d &rotation)
|
||||||
}
|
}
|
||||||
|
|
||||||
Transformation mat_around_a_point_rotate(const Transformation& innMat, const Vec3d &pt, const Vec3d &axis, float rotate_theta_radian);
|
Transformation mat_around_a_point_rotate(const Transformation& innMat, const Vec3d &pt, const Vec3d &axis, float rotate_theta_radian);
|
||||||
|
Transformation generate_transform(const Vec3d &x_dir, const Vec3d &y_dir, const Vec3d &z_dir, const Vec3d &origin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a given point is inside a corner of a polygon.
|
* Checks if a given point is inside a corner of a polygon.
|
||||||
|
|
|
@ -1167,23 +1167,27 @@ bool ModelObject::make_boolean(ModelObject *cut_object, const std::string &boole
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelVolume* ModelObject::add_volume(const TriangleMesh &mesh)
|
ModelVolume *ModelObject::add_volume(const TriangleMesh &mesh, bool modify_to_center_geometry)
|
||||||
{
|
{
|
||||||
ModelVolume* v = new ModelVolume(this, mesh);
|
ModelVolume* v = new ModelVolume(this, mesh);
|
||||||
this->volumes.push_back(v);
|
this->volumes.push_back(v);
|
||||||
v->center_geometry_after_creation();
|
if (modify_to_center_geometry) {
|
||||||
this->invalidate_bounding_box();
|
v->center_geometry_after_creation();
|
||||||
|
this->invalidate_bounding_box();
|
||||||
|
}
|
||||||
// BBS: backup
|
// BBS: backup
|
||||||
Slic3r::save_object_mesh(*this);
|
Slic3r::save_object_mesh(*this);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelVolume* ModelObject::add_volume(TriangleMesh &&mesh, ModelVolumeType type /*= ModelVolumeType::MODEL_PART*/)
|
ModelVolume *ModelObject::add_volume(TriangleMesh &&mesh, ModelVolumeType type /*= ModelVolumeType::MODEL_PART*/, bool modify_to_center_geometry)
|
||||||
{
|
{
|
||||||
ModelVolume* v = new ModelVolume(this, std::move(mesh), type);
|
ModelVolume* v = new ModelVolume(this, std::move(mesh), type);
|
||||||
this->volumes.push_back(v);
|
this->volumes.push_back(v);
|
||||||
v->center_geometry_after_creation();
|
if (modify_to_center_geometry) {
|
||||||
this->invalidate_bounding_box();
|
v->center_geometry_after_creation();
|
||||||
|
this->invalidate_bounding_box();
|
||||||
|
}
|
||||||
// BBS: backup
|
// BBS: backup
|
||||||
Slic3r::save_object_mesh(*this);
|
Slic3r::save_object_mesh(*this);
|
||||||
return v;
|
return v;
|
||||||
|
|
|
@ -410,8 +410,8 @@ public:
|
||||||
return global_config.option<T>(config_option);
|
return global_config.option<T>(config_option);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelVolume* add_volume(const TriangleMesh &mesh);
|
ModelVolume* add_volume(const TriangleMesh &mesh, bool modify_to_center_geometry = true);
|
||||||
ModelVolume* add_volume(TriangleMesh &&mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART);
|
ModelVolume* add_volume(TriangleMesh &&mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART, bool modify_to_center_geometry = true);
|
||||||
ModelVolume* add_volume(const ModelVolume &volume, ModelVolumeType type = ModelVolumeType::INVALID);
|
ModelVolume* add_volume(const ModelVolume &volume, ModelVolumeType type = ModelVolumeType::INVALID);
|
||||||
ModelVolume* add_volume(const ModelVolume &volume, TriangleMesh &&mesh);
|
ModelVolume* add_volume(const ModelVolume &volume, TriangleMesh &&mesh);
|
||||||
ModelVolume* add_volume_with_shared_mesh(const ModelVolume &other, ModelVolumeType type = ModelVolumeType::MODEL_PART);
|
ModelVolume* add_volume_with_shared_mesh(const ModelVolume &other, ModelVolumeType type = ModelVolumeType::MODEL_PART);
|
||||||
|
@ -1244,11 +1244,13 @@ public:
|
||||||
m_assemble_initialized = true;
|
m_assemble_initialized = true;
|
||||||
m_assemble_transformation = transformation;
|
m_assemble_transformation = transformation;
|
||||||
}
|
}
|
||||||
void set_assemble_from_transform(Transform3d& transform) {
|
void set_assemble_from_transform(const Transform3d& transform) {
|
||||||
m_assemble_initialized = true;
|
m_assemble_initialized = true;
|
||||||
m_assemble_transformation.set_matrix(transform);
|
m_assemble_transformation.set_matrix(transform);
|
||||||
}
|
}
|
||||||
|
Vec3d get_assemble_offset() const {return m_assemble_transformation.get_offset(); }
|
||||||
void set_assemble_offset(const Vec3d& offset) { m_assemble_transformation.set_offset(offset); }
|
void set_assemble_offset(const Vec3d& offset) { m_assemble_transformation.set_offset(offset); }
|
||||||
|
void set_assemble_rotation(const Vec3d &rotation) { m_assemble_transformation.set_rotation(rotation); }
|
||||||
void rotate_assemble(double angle, const Vec3d& axis) {
|
void rotate_assemble(double angle, const Vec3d& axis) {
|
||||||
m_assemble_transformation.set_rotation(m_assemble_transformation.get_rotation() + Geometry::extract_euler_angles(Eigen::Quaterniond(Eigen::AngleAxisd(angle, axis)).toRotationMatrix()));
|
m_assemble_transformation.set_rotation(m_assemble_transformation.get_rotation() + Geometry::extract_euler_angles(Eigen::Quaterniond(Eigen::AngleAxisd(angle, axis)).toRotationMatrix()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -895,8 +895,13 @@ int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_suppo
|
||||||
}
|
}
|
||||||
|
|
||||||
//BBS: add outline drawing logic
|
//BBS: add outline drawing logic
|
||||||
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix, const GUI::Size& cnv_size,
|
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
|
||||||
std::function<bool(const GLVolume&)> filter_func) const
|
bool disable_cullface,
|
||||||
|
const Transform3d & view_matrix,
|
||||||
|
const Transform3d& projection_matrix,
|
||||||
|
const GUI::Size& cnv_size,
|
||||||
|
std::function<bool(const GLVolume &)> filter_func,
|
||||||
|
bool partly_inside_enable) const
|
||||||
{
|
{
|
||||||
GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
|
GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
|
||||||
if (to_render.empty())
|
if (to_render.empty())
|
||||||
|
@ -964,7 +969,7 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
|
||||||
//shader->set_uniform("print_volume.xy_data", m_render_volume.data);
|
//shader->set_uniform("print_volume.xy_data", m_render_volume.data);
|
||||||
//shader->set_uniform("print_volume.z_data", m_render_volume.zs);
|
//shader->set_uniform("print_volume.z_data", m_render_volume.zs);
|
||||||
|
|
||||||
if (volume.first->partly_inside) {
|
if (volume.first->partly_inside && partly_inside_enable) {
|
||||||
//only partly inside volume need to be painted with boundary check
|
//only partly inside volume need to be painted with boundary check
|
||||||
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);
|
||||||
|
|
|
@ -471,8 +471,14 @@ public:
|
||||||
int get_selection_support_threshold_angle(bool&) const;
|
int get_selection_support_threshold_angle(bool&) const;
|
||||||
// Render the volumes by OpenGL.
|
// Render the volumes by OpenGL.
|
||||||
//BBS: add outline drawing logic
|
//BBS: add outline drawing logic
|
||||||
void render(ERenderType type, bool disable_cullface, const Transform3d& view_matrix, const Transform3d& projection_matrix, const GUI::Size& cnv_size,
|
void render(ERenderType type,
|
||||||
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>()) const;
|
bool disable_cullface,
|
||||||
|
const Transform3d & view_matrix,
|
||||||
|
const Transform3d& projection_matrix,
|
||||||
|
const GUI::Size& cnv_size,
|
||||||
|
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>(),
|
||||||
|
bool partly_inside_enable =true
|
||||||
|
) const;
|
||||||
|
|
||||||
// Clear the geometry
|
// Clear the geometry
|
||||||
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
void clear() { for (auto *v : volumes) delete v; volumes.clear(); }
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "libslic3r/Technologies.hpp"
|
#include "libslic3r/Technologies.hpp"
|
||||||
#include "libslic3r/Tesselate.hpp"
|
#include "libslic3r/Tesselate.hpp"
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
#include "3DBed.hpp"
|
|
||||||
#include "3DScene.hpp"
|
#include "3DScene.hpp"
|
||||||
#include "BackgroundSlicingProcess.hpp"
|
#include "BackgroundSlicingProcess.hpp"
|
||||||
#include "GLShader.hpp"
|
#include "GLShader.hpp"
|
||||||
|
@ -1168,6 +1167,13 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed)
|
||||||
load_arrange_settings();
|
load_arrange_settings();
|
||||||
|
|
||||||
m_selection.set_volumes(&m_volumes.volumes);
|
m_selection.set_volumes(&m_volumes.volumes);
|
||||||
|
|
||||||
|
m_assembly_view_desc["object_selection_caption"] = _L("Left mouse button");
|
||||||
|
m_assembly_view_desc["object_selection"] = _L("object selection");
|
||||||
|
m_assembly_view_desc["part_selection_caption"] = "Alt +" + _L("Left mouse button");
|
||||||
|
m_assembly_view_desc["part_selection"] = _L("part selectiont");
|
||||||
|
m_assembly_view_desc["number_key_caption"] = "1~16 " + _L("number keys");
|
||||||
|
m_assembly_view_desc["number_key"] = _L("number keys can quickly change the color of objects");
|
||||||
}
|
}
|
||||||
|
|
||||||
GLCanvas3D::~GLCanvas3D()
|
GLCanvas3D::~GLCanvas3D()
|
||||||
|
@ -1939,7 +1945,11 @@ void GLCanvas3D::render(bool only_init)
|
||||||
/* assemble render*/
|
/* assemble render*/
|
||||||
else if (m_canvas_type == ECanvasType::CanvasAssembleView) {
|
else if (m_canvas_type == ECanvasType::CanvasAssembleView) {
|
||||||
//BBS: add outline logic
|
//BBS: add outline logic
|
||||||
|
if (m_show_world_axes) {
|
||||||
|
m_axes.render();
|
||||||
|
}
|
||||||
_render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running());
|
_render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running());
|
||||||
|
_render_selection();
|
||||||
//_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), show_axes);
|
//_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), show_axes);
|
||||||
_render_plane();
|
_render_plane();
|
||||||
//BBS: add outline logic insteadof selection under assemble view
|
//BBS: add outline logic insteadof selection under assemble view
|
||||||
|
@ -2147,6 +2157,9 @@ void GLCanvas3D::update_plate_thumbnails()
|
||||||
|
|
||||||
void GLCanvas3D::select_all()
|
void GLCanvas3D::select_all()
|
||||||
{
|
{
|
||||||
|
if (!m_gizmos.is_allow_select_all()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
m_selection.add_all();
|
m_selection.add_all();
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
|
@ -2262,16 +2275,10 @@ std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
|
||||||
void GLCanvas3D::mirror_selection(Axis axis)
|
void GLCanvas3D::mirror_selection(Axis axis)
|
||||||
{
|
{
|
||||||
TransformationType transformation_type;
|
TransformationType transformation_type;
|
||||||
if (wxGetApp().obj_manipul()->is_local_coordinates())
|
//transformation_type.set_world();
|
||||||
transformation_type.set_local();
|
|
||||||
else if (wxGetApp().obj_manipul()->is_instance_coordinates())
|
|
||||||
transformation_type.set_instance();
|
|
||||||
|
|
||||||
transformation_type.set_relative();
|
transformation_type.set_relative();
|
||||||
|
|
||||||
m_selection.setup_cache();
|
m_selection.setup_cache();
|
||||||
m_selection.mirror(axis, transformation_type);
|
m_selection.mirror(axis, transformation_type);
|
||||||
|
|
||||||
do_mirror(L("Mirror Object"));
|
do_mirror(L("Mirror Object"));
|
||||||
// BBS
|
// BBS
|
||||||
//wxGetApp().obj_manipul()->set_dirty();
|
//wxGetApp().obj_manipul()->set_dirty();
|
||||||
|
@ -4073,9 +4080,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||||
GLGizmosManager::EType c = m_gizmos.get_current_type();
|
GLGizmosManager::EType c = m_gizmos.get_current_type();
|
||||||
if (current_printer_technology() == ptFFF &&
|
if (current_printer_technology() == ptFFF &&
|
||||||
(fff_print()->config().print_sequence == PrintSequence::ByObject)) {
|
(fff_print()->config().print_sequence == PrintSequence::ByObject)) {
|
||||||
if (c == GLGizmosManager::EType::Move ||
|
if (can_sequential_clearance_show_in_gizmo())
|
||||||
c == GLGizmosManager::EType::Scale ||
|
|
||||||
c == GLGizmosManager::EType::Rotate )
|
|
||||||
update_sequential_clearance();
|
update_sequential_clearance();
|
||||||
} else {
|
} else {
|
||||||
if (c == GLGizmosManager::EType::Move ||
|
if (c == GLGizmosManager::EType::Move ||
|
||||||
|
@ -4178,11 +4183,22 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||||
int volume_idx = get_first_hover_volume_idx();
|
int volume_idx = get_first_hover_volume_idx();
|
||||||
bool already_selected = m_selection.contains_volume(volume_idx);
|
bool already_selected = m_selection.contains_volume(volume_idx);
|
||||||
bool ctrl_down = evt.CmdDown();
|
bool ctrl_down = evt.CmdDown();
|
||||||
|
bool alt_down = evt.AltDown();
|
||||||
Selection::IndicesList curr_idxs = m_selection.get_volume_idxs();
|
Selection::IndicesList curr_idxs = m_selection.get_volume_idxs();
|
||||||
|
|
||||||
if (already_selected && ctrl_down)
|
if (already_selected && ctrl_down)
|
||||||
m_selection.remove(volume_idx);
|
m_selection.remove(volume_idx);
|
||||||
|
else if (alt_down) {
|
||||||
|
Selection::EMode mode = Selection::Volume;
|
||||||
|
if (already_selected) {
|
||||||
|
std::vector<unsigned int> volume_idxs;
|
||||||
|
for (auto idx : curr_idxs) { volume_idxs.emplace_back(idx); }
|
||||||
|
m_selection.remove_volumes(mode, volume_idxs);
|
||||||
|
}
|
||||||
|
std::vector<unsigned int> add_volume_idxs;
|
||||||
|
add_volume_idxs.emplace_back(volume_idx);
|
||||||
|
m_selection.add_volumes(mode, add_volume_idxs, true);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
m_selection.add(volume_idx, !ctrl_down, true);
|
m_selection.add(volume_idx, !ctrl_down, true);
|
||||||
m_mouse.drag.move_requires_threshold = !already_selected;
|
m_mouse.drag.move_requires_threshold = !already_selected;
|
||||||
|
@ -4660,11 +4676,19 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||||
// Move instances/volumes
|
// Move instances/volumes
|
||||||
ModelObject* model_object = m_model->objects[object_idx];
|
ModelObject* model_object = m_model->objects[object_idx];
|
||||||
if (model_object != nullptr) {
|
if (model_object != nullptr) {
|
||||||
if (selection_mode == Selection::Instance)
|
if (selection_mode == Selection::Instance) {
|
||||||
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
if (m_canvas_type == GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||||
|
if ((model_object->instances[instance_idx]->get_assemble_offset() - v->get_instance_offset()).norm() > 1e-2) {
|
||||||
|
model_object->instances[instance_idx]->set_assemble_transformation(v->get_instance_transformation());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (selection_mode == Selection::Volume) {
|
else if (selection_mode == Selection::Volume) {
|
||||||
if (model_object->volumes[volume_idx]->get_transformation() != v->get_volume_transformation()) {
|
auto cur_mv = model_object->volumes[volume_idx];
|
||||||
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
if (cur_mv->get_transformation() != v->get_volume_transformation()) {
|
||||||
|
cur_mv->set_transformation(v->get_volume_transformation());
|
||||||
// BBS: backup
|
// BBS: backup
|
||||||
Slic3r::save_object_mesh(*model_object);
|
Slic3r::save_object_mesh(*model_object);
|
||||||
}
|
}
|
||||||
|
@ -4771,11 +4795,17 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
||||||
// Rotate instances/volumes.
|
// Rotate instances/volumes.
|
||||||
ModelObject* model_object = m_model->objects[object_idx];
|
ModelObject* model_object = m_model->objects[object_idx];
|
||||||
if (model_object != nullptr) {
|
if (model_object != nullptr) {
|
||||||
if (selection_mode == Selection::Instance)
|
if (selection_mode == Selection::Instance) {
|
||||||
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
if (m_canvas_type == GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||||
|
model_object->instances[instance_idx]->set_assemble_from_transform(v->get_instance_transformation().get_matrix());
|
||||||
|
} else {
|
||||||
|
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (selection_mode == Selection::Volume) {
|
else if (selection_mode == Selection::Volume) {
|
||||||
if (model_object->volumes[volume_idx]->get_transformation() != v->get_volume_transformation()) {
|
auto cur_mv = model_object->volumes[volume_idx];
|
||||||
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
if (cur_mv->get_transformation() != v->get_volume_transformation()) {
|
||||||
|
cur_mv->set_transformation(v->get_volume_transformation());
|
||||||
// BBS: backup
|
// BBS: backup
|
||||||
Slic3r::save_object_mesh(*model_object);
|
Slic3r::save_object_mesh(*model_object);
|
||||||
}
|
}
|
||||||
|
@ -4786,23 +4816,24 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
||||||
|
|
||||||
//BBS: notify instance updates to part plater list
|
//BBS: notify instance updates to part plater list
|
||||||
m_selection.notify_instance_update(-1, -1);
|
m_selection.notify_instance_update(-1, -1);
|
||||||
|
if (m_canvas_type != CanvasAssembleView) {
|
||||||
|
// Fixes sinking/flying instances
|
||||||
|
for (const std::pair<int, int> &i : done) {
|
||||||
|
ModelObject *m = m_model->objects[i.first];
|
||||||
|
|
||||||
// Fixes sinking/flying instances
|
// BBS: don't call translate if the z is zero
|
||||||
for (const std::pair<int, int>& i : done) {
|
const double shift_z = m->get_instance_min_z(i.second);
|
||||||
ModelObject* m = m_model->objects[i.first];
|
// leave sinking instances as sinking
|
||||||
|
if ((min_zs.find({i.first, i.second})->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) && (shift_z != 0.0f)) {
|
||||||
|
const Vec3d shift(0.0, 0.0, -shift_z);
|
||||||
|
m_selection.translate(i.first, i.second, shift);
|
||||||
|
m->translate_instance(i.second, shift);
|
||||||
|
// BBS: notify instance updates to part plater list
|
||||||
|
m_selection.notify_instance_update(i.first, i.second);
|
||||||
|
}
|
||||||
|
|
||||||
//BBS: don't call translate if the z is zero
|
wxGetApp().obj_list()->update_info_items(static_cast<size_t>(i.first));
|
||||||
const double shift_z = m->get_instance_min_z(i.second);
|
|
||||||
// leave sinking instances as sinking
|
|
||||||
if ((min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD)&&(shift_z != 0.0f)) {
|
|
||||||
const Vec3d shift(0.0, 0.0, -shift_z);
|
|
||||||
m_selection.translate(i.first, i.second, shift);
|
|
||||||
m->translate_instance(i.second, shift);
|
|
||||||
//BBS: notify instance updates to part plater list
|
|
||||||
m_selection.notify_instance_update(i.first, i.second);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxGetApp().obj_list()->update_info_items(static_cast<size_t>(i.first));
|
|
||||||
}
|
}
|
||||||
//BBS: nofity object list to update
|
//BBS: nofity object list to update
|
||||||
wxGetApp().plater()->sidebar().obj_list()->update_plate_values_for_items();
|
wxGetApp().plater()->sidebar().obj_list()->update_plate_values_for_items();
|
||||||
|
@ -4852,12 +4883,14 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
|
||||||
// Rotate instances/volumes
|
// Rotate instances/volumes
|
||||||
ModelObject* model_object = m_model->objects[object_idx];
|
ModelObject* model_object = m_model->objects[object_idx];
|
||||||
if (model_object != nullptr) {
|
if (model_object != nullptr) {
|
||||||
if (selection_mode == Selection::Instance)
|
if (selection_mode == Selection::Instance) {
|
||||||
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||||
|
}
|
||||||
else if (selection_mode == Selection::Volume) {
|
else if (selection_mode == Selection::Volume) {
|
||||||
if (model_object->volumes[volume_idx]->get_transformation() != v->get_volume_transformation()) {
|
auto cur_mv = model_object->volumes[volume_idx];
|
||||||
|
if (cur_mv->get_transformation() != v->get_volume_transformation()) {
|
||||||
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
|
||||||
model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
|
cur_mv->set_transformation(v->get_volume_transformation());
|
||||||
// BBS: backup
|
// BBS: backup
|
||||||
Slic3r::save_object_mesh(*model_object);
|
Slic3r::save_object_mesh(*model_object);
|
||||||
}
|
}
|
||||||
|
@ -5213,6 +5246,17 @@ void GLCanvas3D::mouse_up_cleanup()
|
||||||
m_canvas->ReleaseMouse();
|
m_canvas->ReleaseMouse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GLCanvas3D::can_sequential_clearance_show_in_gizmo() {
|
||||||
|
switch (m_gizmos.get_current_type()) {
|
||||||
|
case GLGizmosManager::EType::Move:
|
||||||
|
case GLGizmosManager::EType::Scale:
|
||||||
|
case GLGizmosManager::EType::Rotate: {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas3D::update_sequential_clearance()
|
void GLCanvas3D::update_sequential_clearance()
|
||||||
{
|
{
|
||||||
if (current_printer_technology() != ptFFF || (fff_print()->config().print_sequence == PrintSequence::ByLayer))
|
if (current_printer_technology() != ptFFF || (fff_print()->config().print_sequence == PrintSequence::ByLayer))
|
||||||
|
@ -7269,6 +7313,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||||
|
|
||||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud");
|
GLShaderProgram* shader = wxGetApp().get_shader("gouraud");
|
||||||
ECanvasType canvas_type = this->m_canvas_type;
|
ECanvasType canvas_type = this->m_canvas_type;
|
||||||
|
bool partly_inside_enable = canvas_type == ECanvasType::CanvasAssembleView ? false : true;
|
||||||
if (shader != nullptr) {
|
if (shader != nullptr) {
|
||||||
shader->start_using();
|
shader->start_using();
|
||||||
|
|
||||||
|
@ -7312,7 +7357,8 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||||
else {
|
else {
|
||||||
return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
|
return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
partly_inside_enable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -7346,7 +7392,8 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
|
||||||
else {
|
else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
partly_inside_enable);
|
||||||
if (m_canvas_type == CanvasAssembleView && m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position() > 0) {
|
if (m_canvas_type == CanvasAssembleView && m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position() > 0) {
|
||||||
const GLGizmosManager& gm = get_gizmos_manager();
|
const GLGizmosManager& gm = get_gizmos_manager();
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
|
@ -7414,19 +7461,11 @@ void GLCanvas3D::_render_sequential_clearance()
|
||||||
{
|
{
|
||||||
if (m_gizmos.is_dragging())
|
if (m_gizmos.is_dragging())
|
||||||
return;
|
return;
|
||||||
|
auto type = m_gizmos.get_current_type();
|
||||||
switch (m_gizmos.get_current_type())
|
if (type == GLGizmosManager::EType::Undefined
|
||||||
{
|
|| can_sequential_clearance_show_in_gizmo()) {
|
||||||
case GLGizmosManager::EType::Flatten:
|
m_sequential_print_clearance.render();
|
||||||
case GLGizmosManager::EType::Cut:
|
|
||||||
// case GLGizmosManager::EType::Hollow:
|
|
||||||
// case GLGizmosManager::EType::SlaSupports:
|
|
||||||
case GLGizmosManager::EType::FdmSupports:
|
|
||||||
case GLGizmosManager::EType::Seam: { return; }
|
|
||||||
default: { break; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sequential_print_clearance.render();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_RENDER_SELECTION_CENTER
|
#if ENABLE_RENDER_SELECTION_CENTER
|
||||||
|
@ -8171,6 +8210,7 @@ void GLCanvas3D::_render_return_toolbar() const
|
||||||
wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_3D));
|
wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_3D));
|
||||||
const_cast<GLGizmosManager*>(&m_gizmos)->reset_all_states();
|
const_cast<GLGizmosManager*>(&m_gizmos)->reset_all_states();
|
||||||
wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().reset_all_states();
|
wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().reset_all_states();
|
||||||
|
wxGetApp().plater()->get_view3D_canvas3D()->reload_scene(true);
|
||||||
}
|
}
|
||||||
ImGui::PopStyleColor(5);
|
ImGui::PopStyleColor(5);
|
||||||
ImGui::PopStyleVar(1);
|
ImGui::PopStyleVar(1);
|
||||||
|
@ -8370,8 +8410,45 @@ void GLCanvas3D::_render_paint_toolbar() const
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float GLCanvas3D::_show_assembly_tooltip_information(float caption_max, float x, float y) const
|
||||||
|
{
|
||||||
|
ImGuiWrapper *imgui = wxGetApp().imgui();
|
||||||
|
ImTextureID normal_id = m_gizmos.get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
|
||||||
|
ImTextureID hover_id = m_gizmos.get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
|
||||||
|
|
||||||
|
caption_max += imgui->calc_text_size(": "sv).x + 35.f;
|
||||||
|
|
||||||
|
float scale = get_scale();
|
||||||
|
ImVec2 button_size = ImVec2(25 * scale, 25 * scale); // ORCA: Use exact resolution will prevent blur on icon
|
||||||
|
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, {0, ImGui::GetStyle().FramePadding.y});
|
||||||
|
ImGui::ImageButton3(normal_id, hover_id, button_size);
|
||||||
|
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::BeginTooltip2(ImVec2(x, y));
|
||||||
|
auto draw_text_with_caption = [this, &imgui, & caption_max](const wxString &caption, const wxString &text) {
|
||||||
|
imgui->text_colored(ImGuiWrapper::COL_ACTIVE, caption);
|
||||||
|
ImGui::SameLine(caption_max);
|
||||||
|
imgui->text_colored(ImGuiWrapper::COL_WINDOW_BG, text);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &t : std::array<std::string, 3>{"object_selection", "part_selection", "number_key"}) {
|
||||||
|
draw_text_with_caption(m_assembly_view_desc.at(t + "_caption") + ": ", m_assembly_view_desc.at(t));
|
||||||
|
}
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
ImGui::PopStyleVar(2);
|
||||||
|
auto same_line_size = button_size.x * 1.8;//with an space size
|
||||||
|
ImGui::SameLine(same_line_size);
|
||||||
|
same_line_size = imgui->calc_text_size("|"sv).x + same_line_size + imgui->calc_text_size(" "sv).x;
|
||||||
|
imgui->text_colored(ImGuiWrapper::COL_ACTIVE, "|");
|
||||||
|
ImGui::SameLine(same_line_size);
|
||||||
|
return same_line_size;
|
||||||
|
}
|
||||||
|
|
||||||
//BBS
|
//BBS
|
||||||
void GLCanvas3D::_render_assemble_control() const
|
void GLCanvas3D::_render_assemble_control()
|
||||||
{
|
{
|
||||||
if (m_canvas_type != ECanvasType::CanvasAssembleView) {
|
if (m_canvas_type != ECanvasType::CanvasAssembleView) {
|
||||||
GLVolume::explosion_ratio = m_explosion_ratio = 1.0;
|
GLVolume::explosion_ratio = m_explosion_ratio = 1.0;
|
||||||
|
@ -8392,8 +8469,8 @@ void GLCanvas3D::_render_assemble_control() const
|
||||||
const float text_padding = 7.0f;
|
const float text_padding = 7.0f;
|
||||||
const float text_size_x = std::max(imgui->calc_text_size(_L("Reset direction")).x + 2 * ImGui::GetStyle().FramePadding.x,
|
const float text_size_x = std::max(imgui->calc_text_size(_L("Reset direction")).x + 2 * ImGui::GetStyle().FramePadding.x,
|
||||||
std::max(imgui->calc_text_size(_L("Explosion Ratio")).x, imgui->calc_text_size(_L("Section View")).x));
|
std::max(imgui->calc_text_size(_L("Explosion Ratio")).x, imgui->calc_text_size(_L("Section View")).x));
|
||||||
const float slider_width = 75.0f;
|
const float slider_width = 60.0f;
|
||||||
const float value_size = imgui->calc_text_size(std::string_view{"3.00"}).x + text_padding * 2;
|
const float value_size = imgui->calc_text_size("3.00"sv).x + text_padding * 2;
|
||||||
const float item_spacing = imgui->get_item_spacing().x;
|
const float item_spacing = imgui->get_item_spacing().x;
|
||||||
ImVec2 window_padding = ImGui::GetStyle().WindowPadding;
|
ImVec2 window_padding = ImGui::GetStyle().WindowPadding;
|
||||||
|
|
||||||
|
@ -8401,7 +8478,19 @@ void GLCanvas3D::_render_assemble_control() const
|
||||||
imgui->begin(_L("Assemble Control"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
|
imgui->begin(_L("Assemble Control"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
|
||||||
|
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
|
float tip_icon_size;
|
||||||
|
{
|
||||||
|
float caption_max = 0.f;
|
||||||
|
for (const auto &t : std::array<std::string, 3>{"object_selection", "part_selection", "number_key"}) {
|
||||||
|
caption_max = std::max(caption_max, imgui->calc_text_size(m_assembly_view_desc.at(t + "_caption")).x);
|
||||||
|
}
|
||||||
|
const ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||||
|
const float text_y =imgui->calc_text_size(_L("part selection")).y;
|
||||||
|
float get_cur_x = pos.x;
|
||||||
|
float get_cur_y = pos.y - ImGui::GetFrameHeight() - 4 * text_y;
|
||||||
|
tip_icon_size =_show_assembly_tooltip_information(caption_max, get_cur_x, get_cur_y);
|
||||||
|
}
|
||||||
|
float same_line_width = tip_icon_size;
|
||||||
{
|
{
|
||||||
float clp_dist = m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position();
|
float clp_dist = m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position();
|
||||||
if (clp_dist == 0.f) {
|
if (clp_dist == 0.f) {
|
||||||
|
@ -8415,32 +8504,76 @@ void GLCanvas3D::_render_assemble_control() const
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
same_line_width += (text_size_x + item_spacing);
|
||||||
ImGui::SameLine(window_padding.x + text_size_x + item_spacing);
|
ImGui::SameLine(same_line_width);
|
||||||
ImGui::PushItemWidth(slider_width);
|
ImGui::PushItemWidth(slider_width);
|
||||||
bool view_slider_changed = imgui->bbl_slider_float_style("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true);
|
bool view_slider_changed = imgui->bbl_slider_float_style("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true);
|
||||||
|
|
||||||
ImGui::SameLine(window_padding.x + text_size_x + slider_width + item_spacing * 2);
|
same_line_width += (slider_width + item_spacing);
|
||||||
|
ImGui::SameLine(same_line_width);
|
||||||
ImGui::PushItemWidth(value_size);
|
ImGui::PushItemWidth(value_size);
|
||||||
bool view_input_changed = ImGui::BBLDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f");
|
bool view_input_changed = ImGui::BBLDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||||
|
|
||||||
if (view_slider_changed || view_input_changed)
|
if (view_slider_changed || view_input_changed)
|
||||||
m_gizmos.m_assemble_view_data->model_objects_clipper()->set_position(clp_dist, true);
|
m_gizmos.m_assemble_view_data->model_objects_clipper()->set_position(clp_dist, true);
|
||||||
}
|
|
||||||
|
|
||||||
|
same_line_width += (value_size + item_spacing * 2);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
ImGui::SameLine(window_padding.x + text_size_x + slider_width + item_spacing * 6 + value_size);
|
auto temp_x = imgui->calc_text_size(_L("Explosion Ratio")).x;
|
||||||
|
ImGui::SameLine(same_line_width);
|
||||||
|
ImGui::PushItemWidth(temp_x);
|
||||||
imgui->text(_L("Explosion Ratio"));
|
imgui->text(_L("Explosion Ratio"));
|
||||||
|
|
||||||
ImGui::SameLine(window_padding.x + 2 * text_size_x + slider_width + item_spacing * 7 + value_size);
|
same_line_width += (temp_x + item_spacing);
|
||||||
|
ImGui::SameLine(same_line_width);
|
||||||
ImGui::PushItemWidth(slider_width);
|
ImGui::PushItemWidth(slider_width);
|
||||||
bool explosion_slider_changed = imgui->bbl_slider_float_style("##ratio_slider", &m_explosion_ratio, 1.0f, 3.0f, "%1.2f");
|
bool explosion_slider_changed = imgui->bbl_slider_float_style("##ratio_slider", &m_explosion_ratio, 1.0f, 3.0f, "%1.2f");
|
||||||
|
|
||||||
ImGui::SameLine(window_padding.x + 2 * text_size_x + 2 * slider_width + item_spacing * 8 + value_size);
|
same_line_width += (slider_width + item_spacing);
|
||||||
|
ImGui::SameLine(same_line_width);
|
||||||
ImGui::PushItemWidth(value_size);
|
ImGui::PushItemWidth(value_size);
|
||||||
bool explosion_input_changed = ImGui::BBLDragFloat("##ratio_input", &m_explosion_ratio, 0.1f, 1.0f, 3.0f, "%1.2f");
|
bool explosion_input_changed = ImGui::BBLDragFloat("##ratio_input", &m_explosion_ratio, 0.1f, 1.0f, 3.0f, "%1.2f");
|
||||||
|
same_line_width += (value_size + item_spacing*2);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
ImGui::SameLine(same_line_width);
|
||||||
|
// input
|
||||||
|
std::vector<std::string> modes = {_u8L("Object"), _u8L("Part")};
|
||||||
|
int selection_idx = m_selection.get_volume_selection_mode() == Selection::Instance ? 0 : 1;
|
||||||
|
auto label = _u8L("Selection Mode") + ":" ;
|
||||||
|
auto label_width = imgui->calc_text_size(label).x ;
|
||||||
|
auto item_width = imgui->calc_text_size(_u8L("Object")).x * 2.5 + imgui->calc_text_size("xx"sv).x+ item_spacing;
|
||||||
|
//render imgui
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
ImGui::PushItemWidth(label_width);
|
||||||
|
imgui->text(label);
|
||||||
|
same_line_width += (label_width + item_spacing);
|
||||||
|
ImGui::SameLine(same_line_width);
|
||||||
|
ImGui::PushItemWidth(item_width);
|
||||||
|
size_t selection_out = selection_idx;
|
||||||
|
const char *selected_str = (selection_idx >= 0 && selection_idx < int(modes.size())) ? modes[selection_idx].c_str() : "";
|
||||||
|
ImGuiWrapper::push_combo_style(get_scale());
|
||||||
|
if (ImGui::BBLBeginCombo(("##" + label).c_str(), selected_str, 0)) {
|
||||||
|
for (size_t line_idx = 0; line_idx < modes.size(); ++line_idx) {
|
||||||
|
ImGui::PushID(int(line_idx));
|
||||||
|
if (ImGui::Selectable("", line_idx == selection_idx))
|
||||||
|
selection_out = line_idx;
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("%s", modes[line_idx].c_str());
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
ImGuiWrapper::pop_combo_style();
|
||||||
|
if (selection_idx != selection_out) {//do
|
||||||
|
if (selection_out == 0) { m_selection.unlock_volume_selection_mode(); }
|
||||||
|
m_selection.set_volume_selection_mode(selection_out == 1 ? Selection::Volume : Selection::Instance);
|
||||||
|
if (selection_out == 1) { m_selection.lock_volume_selection_mode(); }
|
||||||
|
}
|
||||||
|
same_line_width += (label_width + item_width);
|
||||||
|
}
|
||||||
imgui->end();
|
imgui->end();
|
||||||
|
|
||||||
ImGuiWrapper::pop_toolbar_style();
|
ImGuiWrapper::pop_toolbar_style();
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include "Camera.hpp"
|
#include "Camera.hpp"
|
||||||
#include "SceneRaycaster.hpp"
|
#include "SceneRaycaster.hpp"
|
||||||
#include "IMToolbar.hpp"
|
#include "IMToolbar.hpp"
|
||||||
|
#include "slic3r/GUI/3DBed.hpp"
|
||||||
#include "libslic3r/Slicing.hpp"
|
#include "libslic3r/Slicing.hpp"
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
@ -512,6 +512,7 @@ private:
|
||||||
wxGLContext* m_context;
|
wxGLContext* m_context;
|
||||||
SceneRaycaster m_scene_raycaster;
|
SceneRaycaster m_scene_raycaster;
|
||||||
Bed3D &m_bed;
|
Bed3D &m_bed;
|
||||||
|
std::map<std::string, wxString> m_assembly_view_desc;
|
||||||
#if ENABLE_RETINA_GL
|
#if ENABLE_RETINA_GL
|
||||||
std::unique_ptr<RetinaHelper> m_retina_helper;
|
std::unique_ptr<RetinaHelper> m_retina_helper;
|
||||||
#endif
|
#endif
|
||||||
|
@ -611,8 +612,8 @@ private:
|
||||||
|
|
||||||
PrinterTechnology current_printer_technology() const;
|
PrinterTechnology current_printer_technology() const;
|
||||||
|
|
||||||
|
bool m_show_world_axes{false};
|
||||||
|
Bed3D::Axes m_axes;
|
||||||
//BBS:record key botton frequency
|
//BBS:record key botton frequency
|
||||||
int auto_orient_count = 0;
|
int auto_orient_count = 0;
|
||||||
int auto_arrange_count = 0;
|
int auto_arrange_count = 0;
|
||||||
|
@ -807,6 +808,7 @@ public:
|
||||||
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(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 set_color_clip_plane_colors(const std::array<ColorRGBA, 2>& colors) { m_volumes.set_color_clip_plane_colors(colors); }
|
||||||
|
|
||||||
|
void set_show_world_axes(bool flag) { m_show_world_axes = flag; }
|
||||||
void refresh_camera_scene_box();
|
void refresh_camera_scene_box();
|
||||||
void set_color_by(const std::string& value);
|
void set_color_by(const std::string& value);
|
||||||
|
|
||||||
|
@ -1111,6 +1113,7 @@ public:
|
||||||
m_sequential_print_clearance.set_polygons(polygons, height_polygons);
|
m_sequential_print_clearance.set_polygons(polygons, height_polygons);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool can_sequential_clearance_show_in_gizmo();
|
||||||
void update_sequential_clearance();
|
void update_sequential_clearance();
|
||||||
|
|
||||||
const Print* fff_print() const;
|
const Print* fff_print() const;
|
||||||
|
@ -1189,7 +1192,8 @@ private:
|
||||||
// BBS
|
// BBS
|
||||||
//void _render_view_toolbar() const;
|
//void _render_view_toolbar() const;
|
||||||
void _render_paint_toolbar() const;
|
void _render_paint_toolbar() const;
|
||||||
void _render_assemble_control() const;
|
float _show_assembly_tooltip_information(float caption_max, float x, float y) const;
|
||||||
|
void _render_assemble_control();
|
||||||
void _render_assemble_info() const;
|
void _render_assemble_info() const;
|
||||||
#if ENABLE_SHOW_CAMERA_TARGET
|
#if ENABLE_SHOW_CAMERA_TARGET
|
||||||
void _render_camera_target();
|
void _render_camera_target();
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace GUI {
|
||||||
|
|
||||||
enum class ECoordinatesType : unsigned char
|
enum class ECoordinatesType : unsigned char
|
||||||
{
|
{
|
||||||
World,
|
World = 0,
|
||||||
Instance,
|
Instance,
|
||||||
Local
|
Local
|
||||||
};
|
};
|
||||||
|
|
|
@ -4759,6 +4759,9 @@ void ObjectList::select_all()
|
||||||
|
|
||||||
void ObjectList::select_item_all_children()
|
void ObjectList::select_item_all_children()
|
||||||
{
|
{
|
||||||
|
if (wxGetApp().plater() && !wxGetApp().plater()->canvas3D()->get_gizmos_manager().is_allow_select_all()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
wxDataViewItemArray sels;
|
wxDataViewItemArray sels;
|
||||||
|
|
||||||
// There is no selection before OR some object is selected => select all objects
|
// There is no selection before OR some object is selected => select all objects
|
||||||
|
|
|
@ -823,10 +823,10 @@ bool AssembleView::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrint
|
||||||
m_canvas->enable_assemble_view_toolbar(false);
|
m_canvas->enable_assemble_view_toolbar(false);
|
||||||
m_canvas->enable_return_toolbar(true);
|
m_canvas->enable_return_toolbar(true);
|
||||||
m_canvas->enable_separator_toolbar(false);
|
m_canvas->enable_separator_toolbar(false);
|
||||||
|
//m_canvas->set_show_world_axes(true);//wait for GitHub users to see if they have this requirement
|
||||||
// BBS: set volume_selection_mode to Volume
|
// BBS: set volume_selection_mode to Volume
|
||||||
m_canvas->get_selection().set_volume_selection_mode(Selection::Volume);
|
//same to 3d //m_canvas->get_selection().set_volume_selection_mode(Selection::Instance);
|
||||||
m_canvas->get_selection().lock_volume_selection_mode();
|
//m_canvas->get_selection().lock_volume_selection_mode();
|
||||||
|
|
||||||
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
|
main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
|
||||||
|
|
|
@ -227,7 +227,71 @@ bool GLGizmoBase::render_combo(const std::string &label, const std::vector<std::
|
||||||
return is_changed;
|
return is_changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
|
void GLGizmoBase::render_cross_mark(const Vec3f &target, bool is_single)
|
||||||
|
{
|
||||||
|
const float half_length = 4.0f;
|
||||||
|
|
||||||
|
glsafe(::glLineWidth(2.0f));
|
||||||
|
|
||||||
|
auto render_line = [](const Vec3f& p1, const Vec3f& p2, const ColorRGBA& color) {
|
||||||
|
GLModel::Geometry init_data;
|
||||||
|
init_data.format = {GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3};
|
||||||
|
init_data.color = color;
|
||||||
|
init_data.reserve_vertices(2);
|
||||||
|
init_data.reserve_indices(2);
|
||||||
|
|
||||||
|
// vertices
|
||||||
|
init_data.add_vertex(p1);
|
||||||
|
init_data.add_vertex(p2);
|
||||||
|
|
||||||
|
// indices
|
||||||
|
init_data.add_line(0, 1);
|
||||||
|
|
||||||
|
GLModel model;
|
||||||
|
model.init_from(std::move(init_data));
|
||||||
|
model.render();
|
||||||
|
};
|
||||||
|
|
||||||
|
// draw line for x axis
|
||||||
|
if (!is_single) {
|
||||||
|
render_line(
|
||||||
|
{target(0) - half_length, target(1), target(2)},
|
||||||
|
{target(0) + half_length, target(1), target(2)},
|
||||||
|
ColorRGBA::RED());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
render_line(
|
||||||
|
{target(0), target(1), target(2)},
|
||||||
|
{target(0) + half_length, target(1), target(2)},
|
||||||
|
ColorRGBA::RED());
|
||||||
|
}
|
||||||
|
// draw line for y axis
|
||||||
|
if (!is_single) {
|
||||||
|
render_line(
|
||||||
|
{target(0), target(1) - half_length, target(2)},
|
||||||
|
{target(0), target(1) + half_length, target(2)},
|
||||||
|
ColorRGBA::GREEN());
|
||||||
|
} else {
|
||||||
|
render_line(
|
||||||
|
{target(0), target(1), target(2)},
|
||||||
|
{target(0), target(1) + half_length, target(2)},
|
||||||
|
ColorRGBA::GREEN());
|
||||||
|
}
|
||||||
|
// draw line for z axis
|
||||||
|
if (!is_single) {
|
||||||
|
render_line(
|
||||||
|
{target(0), target(1), target(2) - half_length},
|
||||||
|
{target(0), target(1), target(2) + half_length},
|
||||||
|
ColorRGBA::BLUE());
|
||||||
|
} else {
|
||||||
|
render_line(
|
||||||
|
{target(0), target(1), target(2)},
|
||||||
|
{target(0), target(1), target(2) + half_length},
|
||||||
|
ColorRGBA::BLUE());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLGizmoBase::GLGizmoBase(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id)
|
||||||
: m_parent(parent)
|
: m_parent(parent)
|
||||||
, m_group_id(-1)
|
, m_group_id(-1)
|
||||||
, m_state(Off)
|
, m_state(Off)
|
||||||
|
|
|
@ -152,7 +152,7 @@ protected:
|
||||||
|
|
||||||
bool render_combo(const std::string &label, const std::vector<std::string> &lines,
|
bool render_combo(const std::string &label, const std::vector<std::string> &lines,
|
||||||
int &selection_idx, float label_width, float item_width);
|
int &selection_idx, float label_width, float item_width);
|
||||||
|
void render_cross_mark(const Vec3f& target,bool is_single =false);
|
||||||
public:
|
public:
|
||||||
GLGizmoBase(GLCanvas3D& parent,
|
GLGizmoBase(GLCanvas3D& parent,
|
||||||
const std::string& icon_filename,
|
const std::string& icon_filename,
|
||||||
|
|
|
@ -48,6 +48,7 @@ bool GLGizmoMove3D::on_mouse(const wxMouseEvent &mouse_event) {
|
||||||
|
|
||||||
void GLGizmoMove3D::data_changed(bool is_serializing) {
|
void GLGizmoMove3D::data_changed(bool is_serializing) {
|
||||||
m_grabbers[2].enabled = !m_parent.get_selection().is_wipe_tower();
|
m_grabbers[2].enabled = !m_parent.get_selection().is_wipe_tower();
|
||||||
|
change_cs_by_selection();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoMove3D::on_init()
|
bool GLGizmoMove3D::on_init()
|
||||||
|
@ -67,7 +68,11 @@ bool GLGizmoMove3D::on_init()
|
||||||
|
|
||||||
std::string GLGizmoMove3D::on_get_name() const
|
std::string GLGizmoMove3D::on_get_name() const
|
||||||
{
|
{
|
||||||
return _u8L("Move");
|
if (!on_is_activable() && m_state == EState::Off) {
|
||||||
|
return _u8L("Move") + ":\n" + _u8L("Please select at least one object.");
|
||||||
|
} else {
|
||||||
|
return _u8L("Move");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoMove3D::on_is_activable() const
|
bool GLGizmoMove3D::on_is_activable() const
|
||||||
|
@ -75,13 +80,21 @@ bool GLGizmoMove3D::on_is_activable() const
|
||||||
return !m_parent.get_selection().is_empty();
|
return !m_parent.get_selection().is_empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoMove3D::on_set_state() {
|
||||||
|
if (get_state() == On) {
|
||||||
|
m_last_selected_obejct_idx = -1;
|
||||||
|
m_last_selected_volume_idx = -1;
|
||||||
|
change_cs_by_selection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GLGizmoMove3D::on_start_dragging()
|
void GLGizmoMove3D::on_start_dragging()
|
||||||
{
|
{
|
||||||
assert(m_hover_id != -1);
|
assert(m_hover_id != -1);
|
||||||
|
|
||||||
m_displacement = Vec3d::Zero();
|
m_displacement = Vec3d::Zero();
|
||||||
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
|
||||||
m_starting_drag_position = m_grabbers[m_hover_id].center;
|
m_starting_drag_position = m_grabbers[m_hover_id].matrix * m_grabbers[m_hover_id].center;
|
||||||
m_starting_box_center = box.center();
|
m_starting_box_center = box.center();
|
||||||
m_starting_box_bottom_center = box.center();
|
m_starting_box_bottom_center = box.center();
|
||||||
m_starting_box_bottom_center(2) = box.min(2);
|
m_starting_box_bottom_center(2) = box.min(2);
|
||||||
|
@ -121,42 +134,38 @@ void GLGizmoMove3D::on_render()
|
||||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
const auto &[box, box_trafo] = selection.get_bounding_box_in_current_reference_system();
|
||||||
const Vec3d& center = box.center();
|
m_bounding_box = box;
|
||||||
|
m_center = box_trafo.translation();
|
||||||
|
if (m_object_manipulation) {
|
||||||
|
m_object_manipulation->cs_center = box_trafo.translation();
|
||||||
|
}
|
||||||
|
const Transform3d base_matrix = box_trafo;
|
||||||
float space_size = 20.f *INV_ZOOM;
|
float space_size = 20.f *INV_ZOOM;
|
||||||
|
|
||||||
#if ENABLE_FIXED_GRABBER
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
m_grabbers[i].matrix = base_matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vec3d zero = Vec3d::Zero();
|
||||||
|
|
||||||
// x axis
|
// x axis
|
||||||
m_grabbers[0].center = { box.max.x() + space_size, center.y(), center.z() };
|
m_grabbers[0].center = {m_bounding_box.max.x() + space_size, 0, 0};
|
||||||
// y axis
|
// y axis
|
||||||
m_grabbers[1].center = { center.x(), box.max.y() + space_size, center.z() };
|
m_grabbers[1].center = {0, m_bounding_box.max.y() + space_size,0};
|
||||||
// z axis
|
// z axis
|
||||||
m_grabbers[2].center = { center.x(), center.y(), box.max.z() + space_size };
|
m_grabbers[2].center = {0,0, m_bounding_box.max.z() + space_size};
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
m_grabbers[i].color = AXES_COLOR[i];
|
m_grabbers[i].color = AXES_COLOR[i];
|
||||||
m_grabbers[i].hover_color = AXES_HOVER_COLOR[i];
|
m_grabbers[i].hover_color = AXES_HOVER_COLOR[i];
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
// x axis
|
|
||||||
m_grabbers[0].center = { box.max.x() + Offset, center.y(), center.z() };
|
|
||||||
m_grabbers[0].color = AXES_COLOR[0];
|
|
||||||
|
|
||||||
// y axis
|
|
||||||
m_grabbers[1].center = { center.x(), box.max.y() + Offset, center.z() };
|
|
||||||
m_grabbers[1].color = AXES_COLOR[1];
|
|
||||||
|
|
||||||
// z axis
|
|
||||||
m_grabbers[2].center = { center.x(), center.y(), box.max.z() + Offset };
|
|
||||||
m_grabbers[2].color = AXES_COLOR[2];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
|
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
|
||||||
|
|
||||||
auto render_grabber_connection = [this, ¢er](unsigned int id) {
|
auto render_grabber_connection = [this, &zero](unsigned int id) {
|
||||||
if (m_grabbers[id].enabled) {
|
if (m_grabbers[id].enabled) {
|
||||||
//if (!m_grabber_connections[id].model.is_initialized() || !m_grabber_connections[id].old_center.isApprox(center)) {
|
//if (!m_grabber_connections[id].model.is_initialized() || !m_grabber_connections[id].old_center.isApprox(center)) {
|
||||||
m_grabber_connections[id].old_center = center;
|
m_grabber_connections[id].old_center = m_grabbers[id].center;
|
||||||
m_grabber_connections[id].model.reset();
|
m_grabber_connections[id].model.reset();
|
||||||
|
|
||||||
GLModel::Geometry init_data;
|
GLModel::Geometry init_data;
|
||||||
|
@ -166,7 +175,7 @@ void GLGizmoMove3D::on_render()
|
||||||
init_data.reserve_indices(2);
|
init_data.reserve_indices(2);
|
||||||
|
|
||||||
// vertices
|
// vertices
|
||||||
init_data.add_vertex((Vec3f)center.cast<float>());
|
init_data.add_vertex((Vec3f)zero.cast<float>());
|
||||||
init_data.add_vertex((Vec3f)m_grabbers[id].center.cast<float>());
|
init_data.add_vertex((Vec3f)m_grabbers[id].center.cast<float>());
|
||||||
|
|
||||||
// indices
|
// indices
|
||||||
|
@ -186,7 +195,7 @@ void GLGizmoMove3D::on_render()
|
||||||
if (shader != nullptr) {
|
if (shader != nullptr) {
|
||||||
shader->start_using();
|
shader->start_using();
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * base_matrix);
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
|
|
||||||
// draw axes
|
// draw axes
|
||||||
|
@ -199,6 +208,28 @@ void GLGizmoMove3D::on_render()
|
||||||
|
|
||||||
// draw grabbers
|
// draw grabbers
|
||||||
render_grabbers(box);
|
render_grabbers(box);
|
||||||
|
|
||||||
|
if (m_object_manipulation->is_instance_coordinates()) {
|
||||||
|
shader = wxGetApp().get_shader("flat");
|
||||||
|
if (shader != nullptr) {
|
||||||
|
shader->start_using();
|
||||||
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
|
||||||
|
Geometry::Transformation cur_tran;
|
||||||
|
if (auto mi = m_parent.get_selection().get_selected_single_intance()) {
|
||||||
|
cur_tran = mi->get_transformation();
|
||||||
|
} else {
|
||||||
|
cur_tran = selection.get_first_volume()->get_instance_transformation();
|
||||||
|
}
|
||||||
|
|
||||||
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * cur_tran.get_matrix());
|
||||||
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
|
|
||||||
|
render_cross_mark(Vec3f::Zero(), true);
|
||||||
|
|
||||||
|
shader->stop_using();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoMove3D::on_register_raycasters_for_picking()
|
void GLGizmoMove3D::on_register_raycasters_for_picking()
|
||||||
|
@ -245,5 +276,30 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const
|
||||||
|
|
||||||
return projection;
|
return projection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoMove3D::change_cs_by_selection() {
|
||||||
|
int obejct_idx, volume_idx;
|
||||||
|
ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(obejct_idx, volume_idx);
|
||||||
|
if (m_last_selected_obejct_idx == obejct_idx && m_last_selected_volume_idx == volume_idx) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_last_selected_obejct_idx = obejct_idx;
|
||||||
|
m_last_selected_volume_idx = volume_idx;
|
||||||
|
if (m_parent.get_selection().is_multiple_full_object()) {
|
||||||
|
m_object_manipulation->set_use_object_cs(false);
|
||||||
|
}
|
||||||
|
else if (model_volume) {
|
||||||
|
m_object_manipulation->set_use_object_cs(true);
|
||||||
|
} else {
|
||||||
|
m_object_manipulation->set_use_object_cs(false);
|
||||||
|
}
|
||||||
|
if (m_object_manipulation->get_use_object_cs()) {
|
||||||
|
m_object_manipulation->set_coordinates_type(ECoordinatesType::Instance);
|
||||||
|
} else {
|
||||||
|
m_object_manipulation->set_coordinates_type(ECoordinatesType::World);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -16,6 +16,8 @@ class GLGizmoMove3D : public GLGizmoBase
|
||||||
static const double Offset;
|
static const double Offset;
|
||||||
|
|
||||||
Vec3d m_displacement{ Vec3d::Zero() };
|
Vec3d m_displacement{ Vec3d::Zero() };
|
||||||
|
Vec3d m_center{ Vec3d::Zero() };
|
||||||
|
BoundingBoxf3 m_bounding_box;
|
||||||
double m_snap_step{ 1.0 };
|
double m_snap_step{ 1.0 };
|
||||||
Vec3d m_starting_drag_position{ Vec3d::Zero() };
|
Vec3d m_starting_drag_position{ Vec3d::Zero() };
|
||||||
Vec3d m_starting_box_center{ Vec3d::Zero() };
|
Vec3d m_starting_box_center{ Vec3d::Zero() };
|
||||||
|
@ -57,6 +59,7 @@ protected:
|
||||||
bool on_init() override;
|
bool on_init() override;
|
||||||
std::string on_get_name() const override;
|
std::string on_get_name() const override;
|
||||||
bool on_is_activable() const override;
|
bool on_is_activable() const override;
|
||||||
|
virtual void on_set_state() override;
|
||||||
void on_start_dragging() override;
|
void on_start_dragging() override;
|
||||||
void on_stop_dragging() override;
|
void on_stop_dragging() override;
|
||||||
void on_dragging(const UpdateData& data) override;
|
void on_dragging(const UpdateData& data) override;
|
||||||
|
@ -68,6 +71,9 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double calc_projection(const UpdateData& data) const;
|
double calc_projection(const UpdateData& data) const;
|
||||||
|
void change_cs_by_selection(); //cs mean Coordinate System
|
||||||
|
private:
|
||||||
|
int m_last_selected_obejct_idx, m_last_selected_volume_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -527,25 +527,6 @@ bool GLGizmoRotate3D::on_mouse(const wxMouseEvent &mouse_event)
|
||||||
return use_grabbers(mouse_event);
|
return use_grabbers(mouse_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoRotate3D::data_changed(bool is_serializing) {
|
|
||||||
const Selection &selection = m_parent.get_selection();
|
|
||||||
bool is_wipe_tower = selection.is_wipe_tower();
|
|
||||||
if (is_wipe_tower) {
|
|
||||||
DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
|
||||||
float wipe_tower_rotation_angle =
|
|
||||||
dynamic_cast<const ConfigOptionFloat *>(
|
|
||||||
config.option("wipe_tower_rotation_angle"))
|
|
||||||
->value;
|
|
||||||
set_rotation(Vec3d(0., 0., (M_PI / 180.) * wipe_tower_rotation_angle));
|
|
||||||
m_gizmos[0].disable_grabber();
|
|
||||||
m_gizmos[1].disable_grabber();
|
|
||||||
} else {
|
|
||||||
set_rotation(Vec3d::Zero());
|
|
||||||
m_gizmos[0].enable_grabber();
|
|
||||||
m_gizmos[1].enable_grabber();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLGizmoRotate3D::on_init()
|
bool GLGizmoRotate3D::on_init()
|
||||||
{
|
{
|
||||||
for (GLGizmoRotate& g : m_gizmos)
|
for (GLGizmoRotate& g : m_gizmos)
|
||||||
|
@ -561,7 +542,57 @@ bool GLGizmoRotate3D::on_init()
|
||||||
|
|
||||||
std::string GLGizmoRotate3D::on_get_name() const
|
std::string GLGizmoRotate3D::on_get_name() const
|
||||||
{
|
{
|
||||||
return _u8L("Rotate");
|
if (!on_is_activable() && m_state == EState::Off) {
|
||||||
|
return _u8L("Rotate") + ":\n" + _u8L("Please select at least one object.");
|
||||||
|
} else {
|
||||||
|
return _u8L("Rotate");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoRotate3D::on_set_state()
|
||||||
|
{
|
||||||
|
for (GLGizmoRotate &g : m_gizmos)
|
||||||
|
g.set_state(m_state);
|
||||||
|
if (get_state() == On) {
|
||||||
|
m_object_manipulation->set_coordinates_type(ECoordinatesType::World);
|
||||||
|
} else {
|
||||||
|
m_last_volume = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoRotate3D::data_changed(bool is_serializing) {
|
||||||
|
const Selection &selection = m_parent.get_selection();
|
||||||
|
const GLVolume * volume = selection.get_first_volume();
|
||||||
|
if (volume == nullptr) {
|
||||||
|
m_last_volume = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_last_volume != volume) {
|
||||||
|
m_last_volume = volume;
|
||||||
|
Geometry::Transformation tran;
|
||||||
|
if (selection.is_single_full_instance()) {
|
||||||
|
tran = volume->get_instance_transformation();
|
||||||
|
} else {
|
||||||
|
tran = volume->get_volume_transformation();
|
||||||
|
}
|
||||||
|
m_object_manipulation->set_init_rotation(tran);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_wipe_tower = selection.is_wipe_tower();
|
||||||
|
if (is_wipe_tower) {
|
||||||
|
DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
|
float wipe_tower_rotation_angle =
|
||||||
|
dynamic_cast<const ConfigOptionFloat *>(
|
||||||
|
config.option("wipe_tower_rotation_angle"))
|
||||||
|
->value;
|
||||||
|
set_rotation(Vec3d(0., 0., (M_PI / 180.) * wipe_tower_rotation_angle));
|
||||||
|
m_gizmos[0].disable_grabber();
|
||||||
|
m_gizmos[1].disable_grabber();
|
||||||
|
} else {
|
||||||
|
set_rotation(Vec3d::Zero());
|
||||||
|
m_gizmos[0].enable_grabber();
|
||||||
|
m_gizmos[1].enable_grabber();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoRotate3D::on_is_activable() const
|
bool GLGizmoRotate3D::on_is_activable() const
|
||||||
|
|
|
@ -151,11 +151,9 @@ public:
|
||||||
protected:
|
protected:
|
||||||
bool on_init() override;
|
bool on_init() override;
|
||||||
std::string on_get_name() const override;
|
std::string on_get_name() const override;
|
||||||
void on_set_state() override {
|
void on_set_state() override;
|
||||||
for (GLGizmoRotate& g : m_gizmos)
|
void on_set_hover_id() override
|
||||||
g.set_state(m_state);
|
{
|
||||||
}
|
|
||||||
void on_set_hover_id() override {
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
|
m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
|
||||||
}
|
}
|
||||||
|
@ -179,7 +177,7 @@ protected:
|
||||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const GLVolume *m_last_volume;
|
||||||
class RotoptimzeWindow
|
class RotoptimzeWindow
|
||||||
{
|
{
|
||||||
ImGuiWrapper *m_imgui = nullptr;
|
ImGuiWrapper *m_imgui = nullptr;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
#include <wx/utils.h>
|
#include <wx/utils.h>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
@ -24,11 +24,11 @@ Vec3d GetIntersectionOfRayAndPlane(Vec3d ray_position, Vec3d ray_dir, Vec3d plan
|
||||||
//BBS: GUI refactor: add obj manipulation
|
//BBS: GUI refactor: add obj manipulation
|
||||||
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation)
|
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation)
|
||||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||||
|
, m_scale(Vec3d::Ones())
|
||||||
|
, m_offset(Vec3d::Zero())
|
||||||
|
, m_snap_step(0.05)
|
||||||
//BBS: GUI refactor: add obj manipulation
|
//BBS: GUI refactor: add obj manipulation
|
||||||
, m_object_manipulation(obj_manipulation)
|
, m_object_manipulation(obj_manipulation)
|
||||||
, m_base_color(DEFAULT_BASE_COLOR)
|
|
||||||
, m_drag_color(DEFAULT_DRAG_COLOR)
|
|
||||||
, m_highlight_color(DEFAULT_HIGHLIGHT_COLOR)
|
|
||||||
{
|
{
|
||||||
m_grabber_connections[0].grabber_indices = { 0, 1 };
|
m_grabber_connections[0].grabber_indices = { 0, 1 };
|
||||||
m_grabber_connections[1].grabber_indices = { 2, 3 };
|
m_grabber_connections[1].grabber_indices = { 2, 3 };
|
||||||
|
@ -39,6 +39,17 @@ GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filen
|
||||||
m_grabber_connections[6].grabber_indices = { 9, 6 };
|
m_grabber_connections[6].grabber_indices = { 9, 6 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Vec3d &GLGizmoScale3D::get_scale()
|
||||||
|
{
|
||||||
|
if (m_object_manipulation) {
|
||||||
|
Vec3d cache_scale = m_object_manipulation->get_cache().scale.cwiseQuotient(Vec3d(100,100,100));
|
||||||
|
Vec3d temp_scale = cache_scale.cwiseProduct(m_scale);
|
||||||
|
m_object_manipulation->limit_scaling_ratio(temp_scale);
|
||||||
|
m_scale = temp_scale.cwiseQuotient(cache_scale);
|
||||||
|
}
|
||||||
|
return m_scale;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GLGizmoScale3D::get_tooltip() const
|
std::string GLGizmoScale3D::get_tooltip() const
|
||||||
{
|
{
|
||||||
const Selection& selection = m_parent.get_selection();
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
@ -70,77 +81,57 @@ std::string GLGizmoScale3D::get_tooltip() const
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static int constraint_id(int grabber_id)
|
|
||||||
{
|
|
||||||
static const std::vector<int> id_map = { 1, 0, 3, 2, 5, 4, 8, 9, 6, 7 };
|
|
||||||
return (0 <= grabber_id && grabber_id < (int)id_map.size()) ? id_map[grabber_id] : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event)
|
bool GLGizmoScale3D::on_mouse(const wxMouseEvent &mouse_event)
|
||||||
{
|
{
|
||||||
if (mouse_event.Dragging()) {
|
if (mouse_event.Dragging()) {
|
||||||
if (m_dragging) {
|
if (m_dragging) {
|
||||||
// Apply new temporary scale factors
|
// Apply new temporary scale factors
|
||||||
Selection& selection = m_parent.get_selection();
|
|
||||||
TransformationType transformation_type;
|
TransformationType transformation_type;
|
||||||
if (selection.is_single_full_instance()) {
|
if (wxGetApp().obj_manipul()->is_local_coordinates())
|
||||||
transformation_type.set_instance();
|
|
||||||
} else if (selection.is_single_volume_or_modifier()) {
|
|
||||||
transformation_type.set_local();
|
transformation_type.set_local();
|
||||||
}
|
else if (wxGetApp().obj_manipul()->is_instance_coordinates())
|
||||||
|
transformation_type.set_instance();
|
||||||
|
|
||||||
transformation_type.set_relative();
|
transformation_type.set_relative();
|
||||||
|
|
||||||
if (mouse_event.AltDown())
|
if (mouse_event.AltDown())
|
||||||
transformation_type.set_independent();
|
transformation_type.set_independent();
|
||||||
|
|
||||||
selection.scale(m_scale, transformation_type);
|
Selection& selection = m_parent.get_selection();
|
||||||
if (m_starting.ctrl_down && m_hover_id < 6) {
|
selection.scale_and_translate(get_scale(), get_offset(), transformation_type);
|
||||||
// constrained scale:
|
|
||||||
// uses the performed scale to calculate the new position of the constrained grabber
|
|
||||||
// and from that calculates the offset (in world coordinates) to be applied to fullfill the constraint
|
|
||||||
update_render_data();
|
|
||||||
const Vec3d constraint_position = m_grabbers[constraint_id(m_hover_id)].center;
|
|
||||||
// re-apply the scale because the selection always applies the transformations with respect to the initial state
|
|
||||||
// set into on_start_dragging() with the call to selection.setup_cache()
|
|
||||||
m_parent.get_selection().scale_and_translate(m_scale, m_starting.pivots[m_hover_id] - constraint_position, transformation_type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return use_grabbers(mouse_event);
|
return use_grabbers(mouse_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoScale3D::data_changed(bool is_serializing)
|
||||||
|
{
|
||||||
|
const Selection &selection = m_parent.get_selection();
|
||||||
|
bool enable_scale_xyz = selection.is_single_full_instance() ||
|
||||||
|
selection.is_single_volume_or_modifier();
|
||||||
|
for (unsigned int i = 0; i < 6; ++i)
|
||||||
|
m_grabbers[i].enabled = enable_scale_xyz;
|
||||||
|
|
||||||
|
set_scale(Vec3d::Ones());
|
||||||
|
|
||||||
|
change_cs_by_selection();
|
||||||
|
}
|
||||||
|
|
||||||
void GLGizmoScale3D::enable_ununiversal_scale(bool enable)
|
void GLGizmoScale3D::enable_ununiversal_scale(bool enable)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
for (unsigned int i = 0; i < 6; ++i)
|
||||||
m_grabbers[i].enabled = enable;
|
m_grabbers[i].enabled = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoScale3D::data_changed(bool is_serializing) {
|
|
||||||
const Selection &selection = m_parent.get_selection();
|
|
||||||
bool enable_scale_xyz = selection.is_single_full_instance() ||
|
|
||||||
selection.is_single_volume_or_modifier();
|
|
||||||
for (unsigned int i = 0; i < 6; ++i)
|
|
||||||
m_grabbers[i].enabled = enable_scale_xyz;
|
|
||||||
|
|
||||||
set_scale(Vec3d::Ones());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLGizmoScale3D::on_init()
|
bool GLGizmoScale3D::on_init()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i)
|
||||||
|
{
|
||||||
m_grabbers.push_back(Grabber());
|
m_grabbers.push_back(Grabber());
|
||||||
}
|
}
|
||||||
|
|
||||||
double half_pi = 0.5 * (double)PI;
|
double half_pi = 0.5 * (double)PI;
|
||||||
|
|
||||||
// x axis
|
|
||||||
m_grabbers[0].angles(1) = half_pi;
|
|
||||||
m_grabbers[1].angles(1) = half_pi;
|
|
||||||
|
|
||||||
// y axis
|
|
||||||
m_grabbers[2].angles(0) = half_pi;
|
|
||||||
m_grabbers[3].angles(0) = half_pi;
|
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
m_grabbers[4].enabled = false;
|
m_grabbers[4].enabled = false;
|
||||||
|
@ -151,7 +142,11 @@ bool GLGizmoScale3D::on_init()
|
||||||
|
|
||||||
std::string GLGizmoScale3D::on_get_name() const
|
std::string GLGizmoScale3D::on_get_name() const
|
||||||
{
|
{
|
||||||
return _u8L("Scale");
|
if (!on_is_activable() && m_state == EState::Off) {
|
||||||
|
return _u8L("Scale") + ":\n" + _u8L("Please select at least one object.");
|
||||||
|
} else {
|
||||||
|
return _u8L("Scale");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmoScale3D::on_is_activable() const
|
bool GLGizmoScale3D::on_is_activable() const
|
||||||
|
@ -160,21 +155,48 @@ bool GLGizmoScale3D::on_is_activable() const
|
||||||
return !selection.is_empty() && !selection.is_wipe_tower();
|
return !selection.is_empty() && !selection.is_wipe_tower();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoScale3D::on_set_state() {
|
||||||
|
if (get_state() == On) {
|
||||||
|
m_last_selected_obejct_idx = -1;
|
||||||
|
m_last_selected_volume_idx = -1;
|
||||||
|
change_cs_by_selection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int constraint_id(int grabber_id)
|
||||||
|
{
|
||||||
|
static const std::vector<int> id_map = {1, 0, 3, 2, 5, 4, 8, 9, 6, 7};
|
||||||
|
return (0 <= grabber_id && grabber_id < (int) id_map.size()) ? id_map[grabber_id] : -1;
|
||||||
|
}
|
||||||
|
|
||||||
void GLGizmoScale3D::on_start_dragging()
|
void GLGizmoScale3D::on_start_dragging()
|
||||||
{
|
{
|
||||||
assert(m_hover_id != -1);
|
if (m_hover_id != -1) {
|
||||||
m_starting.drag_position = m_grabbers[m_hover_id].center;
|
auto grabbers_transform = m_grabbers_tran.get_matrix();
|
||||||
m_starting.plane_center = m_grabbers[4].center;
|
m_starting.drag_position = grabbers_transform * m_grabbers[m_hover_id].center;
|
||||||
m_starting.plane_nromal = m_grabbers[5].center - m_grabbers[4].center;
|
m_starting.plane_center = grabbers_transform * m_grabbers[4].center; // plane_center = bottom center
|
||||||
m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL);
|
m_starting.plane_nromal = (grabbers_transform * m_grabbers[5].center - grabbers_transform * m_grabbers[4].center).normalized();
|
||||||
m_starting.box = m_box;
|
m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL);
|
||||||
|
m_starting.box = m_bounding_box;
|
||||||
|
|
||||||
m_starting.pivots[0] = m_grabbers[1].center;
|
m_starting.center = m_center;
|
||||||
m_starting.pivots[1] = m_grabbers[0].center;
|
m_starting.instance_center = m_instance_center;
|
||||||
m_starting.pivots[2] = m_grabbers[3].center;
|
|
||||||
m_starting.pivots[3] = m_grabbers[2].center;
|
const Vec3d box_half_size = 0.5 * m_bounding_box.size();
|
||||||
m_starting.pivots[4] = m_grabbers[5].center;
|
|
||||||
m_starting.pivots[5] = m_grabbers[4].center;
|
m_starting.local_pivots[0] = Vec3d(box_half_size.x(), 0.0, -box_half_size.z());
|
||||||
|
m_starting.local_pivots[1] = Vec3d(-box_half_size.x(), 0.0, -box_half_size.z());
|
||||||
|
m_starting.local_pivots[2] = Vec3d(0.0, box_half_size.y(), -box_half_size.z());
|
||||||
|
m_starting.local_pivots[3] = Vec3d(0.0, -box_half_size.y(), -box_half_size.z());
|
||||||
|
m_starting.local_pivots[4] = Vec3d(0.0, 0.0, box_half_size.z());
|
||||||
|
m_starting.local_pivots[5] = Vec3d(0.0, 0.0, -box_half_size.z());
|
||||||
|
for (size_t i = 0; i < 6; i++) {
|
||||||
|
m_starting.pivots[i] = grabbers_transform * m_starting.local_pivots[i]; // todo delete
|
||||||
|
}
|
||||||
|
m_starting.constraint_position = grabbers_transform * m_grabbers[constraint_id(m_hover_id)].center;
|
||||||
|
m_scale = m_starting.scale = Vec3d::Ones() ;
|
||||||
|
m_offset = Vec3d::Zero();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoScale3D::on_stop_dragging()
|
void GLGizmoScale3D::on_stop_dragging()
|
||||||
|
@ -185,26 +207,95 @@ void GLGizmoScale3D::on_stop_dragging()
|
||||||
|
|
||||||
void GLGizmoScale3D::on_dragging(const UpdateData& data)
|
void GLGizmoScale3D::on_dragging(const UpdateData& data)
|
||||||
{
|
{
|
||||||
if (m_hover_id == 0 || m_hover_id == 1)
|
if ((m_hover_id == 0) || (m_hover_id == 1))
|
||||||
do_scale_along_axis(X, data);
|
do_scale_along_axis(X, data);
|
||||||
else if (m_hover_id == 2 || m_hover_id == 3)
|
else if ((m_hover_id == 2) || (m_hover_id == 3))
|
||||||
do_scale_along_axis(Y, data);
|
do_scale_along_axis(Y, data);
|
||||||
else if (m_hover_id == 4 || m_hover_id == 5)
|
else if ((m_hover_id == 4) || (m_hover_id == 5))
|
||||||
do_scale_along_axis(Z, data);
|
do_scale_along_axis(Z, data);
|
||||||
else if (m_hover_id >= 6)
|
else if (m_hover_id >= 6)
|
||||||
do_scale_uniform(data);
|
do_scale_uniform(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoScale3D::update_grabbers_data()
|
||||||
|
{
|
||||||
|
const Selection &selection = m_parent.get_selection();
|
||||||
|
const auto &[box, box_trafo] = selection.get_bounding_box_in_current_reference_system();
|
||||||
|
m_bounding_box = box;
|
||||||
|
m_center = box_trafo.translation();
|
||||||
|
m_grabbers_tran.set_matrix(box_trafo);
|
||||||
|
m_instance_center = (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) ? selection.get_first_volume()->get_instance_offset() : m_center;
|
||||||
|
|
||||||
|
const Vec3d box_half_size = 0.5 * m_bounding_box.size();
|
||||||
|
bool ctrl_down = wxGetKeyState(WXK_CONTROL);
|
||||||
|
|
||||||
|
|
||||||
|
bool single_instance = selection.is_single_full_instance();
|
||||||
|
bool single_volume = selection.is_single_modifier() || selection.is_single_volume();
|
||||||
|
|
||||||
|
// x axis
|
||||||
|
m_grabbers[0].center = Vec3d(-(box_half_size.x()), 0.0, -box_half_size.z());
|
||||||
|
m_grabbers[0].color = (ctrl_down && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0];
|
||||||
|
m_grabbers[1].center = Vec3d(box_half_size.x(), 0.0, -box_half_size.z());
|
||||||
|
m_grabbers[1].color = (ctrl_down && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0];
|
||||||
|
// y axis
|
||||||
|
m_grabbers[2].center = Vec3d(0.0, -(box_half_size.y()), -box_half_size.z());
|
||||||
|
m_grabbers[2].color = (ctrl_down && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1];
|
||||||
|
m_grabbers[3].center = Vec3d(0.0, box_half_size.y(), -box_half_size.z());
|
||||||
|
m_grabbers[3].color = (ctrl_down && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1];
|
||||||
|
// z axis do not show 4
|
||||||
|
m_grabbers[4].center = Vec3d(0.0, 0.0, -(box_half_size.z()));
|
||||||
|
m_grabbers[4].enabled = false;
|
||||||
|
|
||||||
|
m_grabbers[5].center = Vec3d(0.0, 0.0, box_half_size.z());
|
||||||
|
m_grabbers[5].color = (ctrl_down && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2];
|
||||||
|
// uniform
|
||||||
|
m_grabbers[6].center = Vec3d(-box_half_size.x(), -box_half_size.y(), -box_half_size.z());
|
||||||
|
m_grabbers[6].color = (ctrl_down && m_hover_id == 8) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
|
||||||
|
m_grabbers[7].center = Vec3d(box_half_size.x(), -box_half_size.y(), -box_half_size.z());
|
||||||
|
m_grabbers[7].color = (ctrl_down && m_hover_id == 9) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
|
||||||
|
m_grabbers[8].center = Vec3d(box_half_size.x(), box_half_size.y(), -box_half_size.z());
|
||||||
|
m_grabbers[8].color = (ctrl_down && m_hover_id == 6) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
|
||||||
|
m_grabbers[9].center = Vec3d(-box_half_size.x(), box_half_size.y(), -box_half_size.z());
|
||||||
|
m_grabbers[9].color = (ctrl_down && m_hover_id == 7) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
|
||||||
|
for (int i = 0; i < 6; ++i) {
|
||||||
|
//m_grabbers[i].color = AXES_COLOR[i / 2];
|
||||||
|
m_grabbers[i].hover_color = AXES_HOVER_COLOR[i / 2];
|
||||||
|
}
|
||||||
|
for (int i = 6; i < 10; ++i) {
|
||||||
|
//m_grabbers[i].color = GRABBER_UNIFORM_COL;
|
||||||
|
m_grabbers[i].hover_color = GRABBER_UNIFORM_HOVER_COL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
m_grabbers[i].matrix = m_grabbers_tran.get_matrix();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GLGizmoScale3D::change_cs_by_selection() {
|
||||||
|
int obejct_idx, volume_idx;
|
||||||
|
ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(obejct_idx, volume_idx);
|
||||||
|
if (m_last_selected_obejct_idx == obejct_idx && m_last_selected_volume_idx == volume_idx) { return; }
|
||||||
|
m_last_selected_obejct_idx = obejct_idx;
|
||||||
|
m_last_selected_volume_idx = volume_idx;
|
||||||
|
if (m_parent.get_selection().is_multiple_full_object()) {
|
||||||
|
m_object_manipulation->set_coordinates_type(ECoordinatesType::World);
|
||||||
|
} else if (model_volume) {
|
||||||
|
m_object_manipulation->set_coordinates_type(ECoordinatesType::Local);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GLGizmoScale3D::on_render()
|
void GLGizmoScale3D::on_render()
|
||||||
{
|
{
|
||||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
update_render_data();
|
update_grabbers_data();
|
||||||
|
|
||||||
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
|
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
|
||||||
|
|
||||||
const float grabber_mean_size = (float) ((m_box.size().x() + m_box.size().y() + m_box.size().z()) / 3.0);
|
const float grabber_mean_size = (float)((m_bounding_box.size().x() + m_bounding_box.size().y() + m_bounding_box.size().z()) / 3.0);
|
||||||
|
|
||||||
//draw connections
|
//draw connections
|
||||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||||
|
@ -213,7 +304,7 @@ void GLGizmoScale3D::on_render()
|
||||||
// BBS: when select multiple objects, uniform scale can be deselected, display the connection(4,5)
|
// BBS: when select multiple objects, uniform scale can be deselected, display the connection(4,5)
|
||||||
//if (single_instance || single_volume) {
|
//if (single_instance || single_volume) {
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
|
shader->set_uniform("view_model_matrix", camera.get_view_matrix() * m_grabbers_tran.get_matrix());
|
||||||
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||||
if (m_grabbers[4].enabled && m_grabbers[5].enabled)
|
if (m_grabbers[4].enabled && m_grabbers[5].enabled)
|
||||||
render_grabbers_connection(4, 5, m_grabbers[4].color);
|
render_grabbers_connection(4, 5, m_grabbers[4].color);
|
||||||
|
@ -298,29 +389,53 @@ void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit
|
||||||
void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
|
void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
|
||||||
{
|
{
|
||||||
double ratio = calc_ratio(data);
|
double ratio = calc_ratio(data);
|
||||||
if (ratio > 0.0) {
|
if (ratio > 0.0)
|
||||||
Vec3d curr_scale = m_scale;
|
{
|
||||||
curr_scale(axis) = m_starting.scale(axis) * ratio;
|
m_scale(axis) = m_starting.scale(axis) * ratio;
|
||||||
m_scale = curr_scale;
|
if (m_starting.ctrl_down && abs(ratio-1.0f)>0.001) {
|
||||||
|
double local_offset = 0.5 * (m_scale(axis) - m_starting.scale(axis)) * m_starting.box.size()(axis);
|
||||||
|
if (m_hover_id == 2 * axis) {
|
||||||
|
local_offset *= -1.0;
|
||||||
|
}
|
||||||
|
Vec3d local_offset_vec;
|
||||||
|
switch (axis)
|
||||||
|
{
|
||||||
|
case X: { local_offset_vec = local_offset * Vec3d::UnitX(); break; }
|
||||||
|
case Y: { local_offset_vec = local_offset * Vec3d::UnitY(); break;}
|
||||||
|
case Z: { local_offset_vec = local_offset * Vec3d::UnitZ(); break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
if (m_object_manipulation->is_world_coordinates()) {
|
||||||
|
m_offset = local_offset_vec;
|
||||||
|
} else {//if (m_object_manipulation->is_instance_coordinates())
|
||||||
|
m_offset = m_grabbers_tran.get_matrix_no_offset() * local_offset_vec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_offset = Vec3d::Zero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoScale3D::do_scale_uniform(const UpdateData & data)
|
void GLGizmoScale3D::do_scale_uniform(const UpdateData& data)
|
||||||
{
|
{
|
||||||
const double ratio = calc_ratio(data);
|
double ratio = calc_ratio(data);
|
||||||
if (ratio > 0.0)
|
if (ratio > 0.0)
|
||||||
|
{
|
||||||
m_scale = m_starting.scale * ratio;
|
m_scale = m_starting.scale * ratio;
|
||||||
|
m_offset = Vec3d::Zero();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
||||||
{
|
{
|
||||||
double ratio = 0.0;
|
double ratio = 0.0;
|
||||||
|
|
||||||
Vec3d pivot = (m_starting.ctrl_down && m_hover_id < 6) ? m_starting.pivots[m_hover_id] : m_starting.plane_center;
|
Vec3d pivot = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_starting.constraint_position : m_starting.plane_center; // plane_center = bottom center
|
||||||
|
|
||||||
Vec3d starting_vec = m_starting.drag_position - pivot;
|
Vec3d starting_vec = m_starting.drag_position - pivot;
|
||||||
double len_starting_vec = starting_vec.norm();
|
double len_starting_vec = starting_vec.norm();
|
||||||
if (len_starting_vec != 0.0) {
|
if (len_starting_vec != 0.0)
|
||||||
|
{
|
||||||
Vec3d mouse_dir = data.mouse_ray.unit_vector();
|
Vec3d mouse_dir = data.mouse_ray.unit_vector();
|
||||||
Vec3d plane_normal = m_starting.plane_nromal;
|
Vec3d plane_normal = m_starting.plane_nromal;
|
||||||
if (m_hover_id == 5) {
|
if (m_hover_id == 5) {
|
||||||
|
@ -328,10 +443,16 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
||||||
Vec3d plane_vec = mouse_dir.cross(m_starting.plane_nromal);
|
Vec3d plane_vec = mouse_dir.cross(m_starting.plane_nromal);
|
||||||
plane_normal = plane_vec.cross(m_starting.plane_nromal);
|
plane_normal = plane_vec.cross(m_starting.plane_nromal);
|
||||||
}
|
}
|
||||||
|
plane_normal = plane_normal.normalized();
|
||||||
// finds the intersection of the mouse ray with the plane that the drag point moves
|
// finds the intersection of the mouse ray with the plane that the drag point moves
|
||||||
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection
|
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection
|
||||||
Vec3d inters = GetIntersectionOfRayAndPlane(data.mouse_ray.a, mouse_dir, m_starting.drag_position, plane_normal.normalized());
|
auto dot_value = (plane_normal.dot(mouse_dir));
|
||||||
|
auto angle = Geometry::rad2deg(acos(dot_value));
|
||||||
|
auto big_than_min_angle = abs(angle) < 95 && abs(angle) > 85;
|
||||||
|
if (big_than_min_angle) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
Vec3d inters = GetIntersectionOfRayAndPlane(data.mouse_ray.a, mouse_dir, m_starting.drag_position, plane_normal);
|
||||||
|
|
||||||
Vec3d inters_vec = inters - m_starting.drag_position;
|
Vec3d inters_vec = inters - m_starting.drag_position;
|
||||||
|
|
||||||
|
@ -347,78 +468,5 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
|
||||||
return ratio;
|
return ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLGizmoScale3D::update_render_data()
|
|
||||||
{
|
|
||||||
|
|
||||||
const Selection& selection = m_parent.get_selection();
|
|
||||||
|
|
||||||
bool single_instance = selection.is_single_full_instance();
|
|
||||||
bool single_volume = selection.is_single_volume_or_modifier();
|
|
||||||
|
|
||||||
m_box.reset();
|
|
||||||
m_transform = Transform3d::Identity();
|
|
||||||
Vec3d angles = Vec3d::Zero();
|
|
||||||
|
|
||||||
if (single_instance) {
|
|
||||||
// calculate bounding box in instance local reference system
|
|
||||||
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
|
||||||
for (unsigned int idx : idxs) {
|
|
||||||
const GLVolume* vol = selection.get_volume(idx);
|
|
||||||
m_box.merge(vol->bounding_box().transformed(vol->get_volume_transformation().get_matrix()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// gets transform from first selected volume
|
|
||||||
const GLVolume* v = selection.get_first_volume();
|
|
||||||
m_transform = v->get_instance_transformation().get_matrix();
|
|
||||||
// gets angles from first selected volume
|
|
||||||
angles = v->get_instance_rotation();
|
|
||||||
}
|
|
||||||
else if (single_volume) {
|
|
||||||
const GLVolume* v = selection.get_first_volume();
|
|
||||||
m_box = v->bounding_box();
|
|
||||||
m_transform = v->world_matrix();
|
|
||||||
angles = Geometry::extract_euler_angles(m_transform);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_box = selection.get_bounding_box();
|
|
||||||
|
|
||||||
const Vec3d& center = m_box.center();
|
|
||||||
|
|
||||||
// x axis
|
|
||||||
m_grabbers[0].center = m_transform * Vec3d(m_box.min.x(), center.y(), m_box.min.z());
|
|
||||||
m_grabbers[1].center = m_transform * Vec3d(m_box.max.x(), center.y(), m_box.min.z());
|
|
||||||
|
|
||||||
// y axis
|
|
||||||
m_grabbers[2].center = m_transform * Vec3d(center.x(), m_box.min.y(), m_box.min.z());
|
|
||||||
m_grabbers[3].center = m_transform * Vec3d(center.x(), m_box.max.y(), m_box.min.z());
|
|
||||||
|
|
||||||
// z axis do not show 4
|
|
||||||
m_grabbers[4].center = m_transform * Vec3d(center.x(), center.y(), m_box.min.z());
|
|
||||||
m_grabbers[4].enabled = false;
|
|
||||||
|
|
||||||
m_grabbers[5].center = m_transform * Vec3d(center.x(), center.y(), m_box.max.z());
|
|
||||||
|
|
||||||
// uniform
|
|
||||||
m_grabbers[6].center = m_transform * Vec3d(m_box.min.x(), m_box.min.y(), m_box.min.z());
|
|
||||||
m_grabbers[7].center = m_transform * Vec3d(m_box.max.x(), m_box.min.y(), m_box.min.z());
|
|
||||||
m_grabbers[8].center = m_transform * Vec3d(m_box.max.x(), m_box.max.y(), m_box.min.z());
|
|
||||||
m_grabbers[9].center = m_transform * Vec3d(m_box.min.x(), m_box.max.y(), m_box.min.z());
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; ++i) {
|
|
||||||
m_grabbers[i].color = AXES_COLOR[i/2];
|
|
||||||
m_grabbers[i].hover_color = AXES_HOVER_COLOR[i/2];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 6; i < 10; ++i) {
|
|
||||||
m_grabbers[i].color = GRABBER_UNIFORM_COL;
|
|
||||||
m_grabbers[i].hover_color = GRABBER_UNIFORM_HOVER_COL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sets grabbers orientation
|
|
||||||
for (int i = 0; i < 10; ++i) {
|
|
||||||
m_grabbers[i].angles = angles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -19,25 +19,28 @@ class GLGizmoScale3D : public GLGizmoBase
|
||||||
{
|
{
|
||||||
Vec3d scale;
|
Vec3d scale;
|
||||||
Vec3d drag_position;
|
Vec3d drag_position;
|
||||||
|
Vec3d constraint_position;
|
||||||
|
Vec3d center{Vec3d::Zero()};//sphere bounding box center
|
||||||
|
Vec3d instance_center{Vec3d::Zero()};
|
||||||
Vec3d plane_center; // keep the relative center position for scale in the bottom plane
|
Vec3d plane_center; // keep the relative center position for scale in the bottom plane
|
||||||
Vec3d plane_nromal; // keep the bottom plane
|
Vec3d plane_nromal; // keep the bottom plane
|
||||||
BoundingBoxf3 box;
|
BoundingBoxf3 box;
|
||||||
Vec3d pivots[6];
|
Vec3d pivots[6];// Vec3d constraint_position{Vec3d::Zero()};
|
||||||
|
Vec3d local_pivots[6];
|
||||||
bool ctrl_down;
|
bool ctrl_down;
|
||||||
|
|
||||||
StartingData() : scale(Vec3d::Ones()), drag_position(Vec3d::Zero()), ctrl_down(false) { for (int i = 0; i < 5; ++i) { pivots[i] = Vec3d::Zero(); } }
|
StartingData() : scale(Vec3d::Ones()), drag_position(Vec3d::Zero()), ctrl_down(false) { for (int i = 0; i < 5; ++i) { pivots[i] = Vec3d::Zero(); } }
|
||||||
};
|
};
|
||||||
|
|
||||||
BoundingBoxf3 m_box;
|
mutable BoundingBoxf3 m_bounding_box;
|
||||||
Transform3d m_transform;
|
Geometry::Transformation m_grabbers_tran;//m_grabbers_transform
|
||||||
Vec3d m_scale{ Vec3d::Ones() };
|
Vec3d m_center{Vec3d::Zero()};
|
||||||
double m_snap_step{ 0.05 };
|
Vec3d m_instance_center{Vec3d::Zero()};
|
||||||
|
Vec3d m_scale;
|
||||||
|
Vec3d m_offset;
|
||||||
|
double m_snap_step;
|
||||||
StartingData m_starting;
|
StartingData m_starting;
|
||||||
|
|
||||||
ColorRGBA m_base_color;
|
|
||||||
ColorRGBA m_drag_color;
|
|
||||||
ColorRGBA m_highlight_color;
|
|
||||||
|
|
||||||
struct GrabberConnection
|
struct GrabberConnection
|
||||||
{
|
{
|
||||||
GLModel model;
|
GLModel model;
|
||||||
|
@ -58,9 +61,11 @@ public:
|
||||||
double get_snap_step(double step) const { return m_snap_step; }
|
double get_snap_step(double step) const { return m_snap_step; }
|
||||||
void set_snap_step(double step) { m_snap_step = step; }
|
void set_snap_step(double step) { m_snap_step = step; }
|
||||||
|
|
||||||
const Vec3d& get_scale() const { return m_scale; }
|
const Vec3d &get_scale();
|
||||||
void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; }
|
void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; }
|
||||||
|
|
||||||
|
const Vec3d& get_offset() const { return m_offset; }
|
||||||
|
|
||||||
std::string get_tooltip() const override;
|
std::string get_tooltip() const override;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -76,6 +81,7 @@ protected:
|
||||||
virtual bool on_init() override;
|
virtual bool on_init() override;
|
||||||
virtual std::string on_get_name() const override;
|
virtual std::string on_get_name() const override;
|
||||||
virtual bool on_is_activable() const override;
|
virtual bool on_is_activable() const override;
|
||||||
|
virtual void on_set_state() override;
|
||||||
virtual void on_start_dragging() override;
|
virtual void on_start_dragging() override;
|
||||||
virtual void on_stop_dragging() override;
|
virtual void on_stop_dragging() override;
|
||||||
virtual void on_dragging(const UpdateData& data) override;
|
virtual void on_dragging(const UpdateData& data) override;
|
||||||
|
@ -92,7 +98,10 @@ private:
|
||||||
void do_scale_uniform(const UpdateData& data);
|
void do_scale_uniform(const UpdateData& data);
|
||||||
|
|
||||||
double calc_ratio(const UpdateData& data) const;
|
double calc_ratio(const UpdateData& data) const;
|
||||||
void update_render_data();
|
void update_grabbers_data();
|
||||||
|
void change_cs_by_selection(); // cs mean Coordinate System
|
||||||
|
private:
|
||||||
|
int m_last_selected_obejct_idx, m_last_selected_volume_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1024,20 +1024,6 @@ void GLGizmoText::show_tooltip_information(float x, float y)
|
||||||
ImGui::PopStyleVar(2);
|
ImGui::PopStyleVar(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelVolume *GLGizmoText::get_selected_single_volume(int &out_object_idx, int &out_volume_idx) const
|
|
||||||
{
|
|
||||||
if (m_parent.get_selection().is_single_volume() || m_parent.get_selection().is_single_modifier()) {
|
|
||||||
const Selection &selection = m_parent.get_selection();
|
|
||||||
const GLVolume * gl_volume = selection.get_first_volume();
|
|
||||||
out_object_idx = gl_volume->object_idx();
|
|
||||||
ModelObject *model_object = selection.get_model()->objects[out_object_idx];
|
|
||||||
out_volume_idx = gl_volume->volume_idx();
|
|
||||||
if (out_volume_idx < model_object->volumes.size())
|
|
||||||
return model_object->volumes[out_volume_idx];
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLGizmoText::reset_text_info()
|
void GLGizmoText::reset_text_info()
|
||||||
{
|
{
|
||||||
m_font_name = "";
|
m_font_name = "";
|
||||||
|
|
|
@ -62,7 +62,9 @@ std::vector<size_t> GLGizmosManager::get_selectable_idxs() const
|
||||||
out.reserve(m_gizmos.size());
|
out.reserve(m_gizmos.size());
|
||||||
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
|
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
|
||||||
for (size_t i = 0; i < m_gizmos.size(); ++i)
|
for (size_t i = 0; i < m_gizmos.size(); ++i)
|
||||||
if (m_gizmos[i]->get_sprite_id() == (unsigned int) Measure ||
|
if (m_gizmos[i]->get_sprite_id() == (unsigned int) Move ||
|
||||||
|
m_gizmos[i]->get_sprite_id() == (unsigned int) Rotate ||
|
||||||
|
m_gizmos[i]->get_sprite_id() == (unsigned int) Measure ||
|
||||||
m_gizmos[i]->get_sprite_id() == (unsigned int) Assembly ||
|
m_gizmos[i]->get_sprite_id() == (unsigned int) Assembly ||
|
||||||
m_gizmos[i]->get_sprite_id() == (unsigned int) MmuSegmentation)
|
m_gizmos[i]->get_sprite_id() == (unsigned int) MmuSegmentation)
|
||||||
out.push_back(i);
|
out.push_back(i);
|
||||||
|
@ -247,6 +249,16 @@ bool GLGizmosManager::init_icon_textures()
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/toolbar_reset_zero.svg", 14, 14, texture_id))
|
||||||
|
icon_list.insert(std::make_pair((int) IC_TOOLBAR_RESET_ZERO, texture_id));
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/toolbar_reset_zero_hover.svg", 14, 14, texture_id))
|
||||||
|
icon_list.insert(std::make_pair((int) IC_TOOLBAR_RESET_ZERO_HOVER, texture_id));
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/toolbar_tooltip.svg", 25, 25, texture_id)) // ORCA: Use same resolution with gizmos to prevent blur on icon
|
if (IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/toolbar_tooltip.svg", 25, 25, texture_id)) // ORCA: Use same resolution with gizmos to prevent blur on icon
|
||||||
icon_list.insert(std::make_pair((int)IC_TOOLBAR_TOOLTIP, texture_id));
|
icon_list.insert(std::make_pair((int)IC_TOOLBAR_TOOLTIP, texture_id));
|
||||||
else
|
else
|
||||||
|
@ -371,6 +383,9 @@ void GLGizmosManager::update_assemble_view_data()
|
||||||
void GLGizmosManager::update_data()
|
void GLGizmosManager::update_data()
|
||||||
{
|
{
|
||||||
if (!m_enabled) return;
|
if (!m_enabled) return;
|
||||||
|
|
||||||
|
const Selection& selection = m_parent.get_selection();
|
||||||
|
|
||||||
if (m_common_gizmos_data)
|
if (m_common_gizmos_data)
|
||||||
m_common_gizmos_data->update(get_current()
|
m_common_gizmos_data->update(get_current()
|
||||||
? get_current()->get_requirements()
|
? get_current()->get_requirements()
|
||||||
|
@ -381,8 +396,10 @@ void GLGizmosManager::update_data()
|
||||||
if (m_current != Flatten && !m_gizmos.empty()) m_gizmos[Flatten]->data_changed(m_serializing);
|
if (m_current != Flatten && !m_gizmos.empty()) m_gizmos[Flatten]->data_changed(m_serializing);
|
||||||
|
|
||||||
//BBS: GUI refactor: add object manipulation in gizmo
|
//BBS: GUI refactor: add object manipulation in gizmo
|
||||||
m_object_manipulation.update_ui_from_settings();
|
if (!selection.is_empty()) {
|
||||||
m_object_manipulation.UpdateAndShow(true);
|
m_object_manipulation.update_ui_from_settings();
|
||||||
|
m_object_manipulation.UpdateAndShow(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLGizmosManager::is_running() const
|
bool GLGizmosManager::is_running() const
|
||||||
|
@ -461,6 +478,22 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GLGizmosManager::is_paint_gizmo()
|
||||||
|
{
|
||||||
|
return m_current == EType::FdmSupports ||
|
||||||
|
m_current == EType::MmuSegmentation ||
|
||||||
|
m_current == EType::Seam;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLGizmosManager::is_allow_select_all() {
|
||||||
|
if (m_current == Undefined || m_current == EType::Move||
|
||||||
|
m_current == EType::Rotate ||
|
||||||
|
m_current == EType::Scale) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ClippingPlane GLGizmosManager::get_clipping_plane() const
|
ClippingPlane GLGizmosManager::get_clipping_plane() const
|
||||||
{
|
{
|
||||||
if (! m_common_gizmos_data
|
if (! m_common_gizmos_data
|
||||||
|
|
|
@ -164,6 +164,8 @@ public:
|
||||||
enum MENU_ICON_NAME {
|
enum MENU_ICON_NAME {
|
||||||
IC_TOOLBAR_RESET = 0,
|
IC_TOOLBAR_RESET = 0,
|
||||||
IC_TOOLBAR_RESET_HOVER,
|
IC_TOOLBAR_RESET_HOVER,
|
||||||
|
IC_TOOLBAR_RESET_ZERO,
|
||||||
|
IC_TOOLBAR_RESET_ZERO_HOVER,
|
||||||
IC_TOOLBAR_TOOLTIP,
|
IC_TOOLBAR_TOOLTIP,
|
||||||
IC_TOOLBAR_TOOLTIP_HOVER,
|
IC_TOOLBAR_TOOLTIP_HOVER,
|
||||||
IC_NAME_COUNT,
|
IC_NAME_COUNT,
|
||||||
|
@ -261,6 +263,8 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_paint_gizmo();
|
||||||
|
bool is_allow_select_all();
|
||||||
ClippingPlane get_clipping_plane() const;
|
ClippingPlane get_clipping_plane() const;
|
||||||
ClippingPlane get_assemble_view_clipping_plane() const;
|
ClippingPlane get_assemble_view_clipping_plane() const;
|
||||||
bool wants_reslice_supports_on_undo() const;
|
bool wants_reslice_supports_on_undo() const;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "libslic3r/Point.hpp"
|
#include "libslic3r/Point.hpp"
|
||||||
|
#include "libslic3r/Geometry.hpp"
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
#include "slic3r/GUI/GUI_Geometry.hpp"
|
#include "slic3r/GUI/GUI_Geometry.hpp"
|
||||||
|
@ -30,6 +31,8 @@ public:
|
||||||
Vec3d position_rounded;
|
Vec3d position_rounded;
|
||||||
Vec3d rotation;
|
Vec3d rotation;
|
||||||
Vec3d rotation_rounded;
|
Vec3d rotation_rounded;
|
||||||
|
Vec3d absolute_rotation;
|
||||||
|
Vec3d absolute_rotation_rounded;
|
||||||
Vec3d scale;
|
Vec3d scale;
|
||||||
Vec3d scale_rounded;
|
Vec3d scale_rounded;
|
||||||
Vec3d size;
|
Vec3d size;
|
||||||
|
@ -56,7 +59,7 @@ public:
|
||||||
Cache m_cache;
|
Cache m_cache;
|
||||||
|
|
||||||
bool m_imperial_units { false };
|
bool m_imperial_units { false };
|
||||||
|
bool m_use_object_cs{false};
|
||||||
// Mirroring buttons and their current state
|
// Mirroring buttons and their current state
|
||||||
//enum MirrorButtonState {
|
//enum MirrorButtonState {
|
||||||
// mbHidden,
|
// mbHidden,
|
||||||
|
@ -75,19 +78,28 @@ public:
|
||||||
std::string m_new_unit_string;
|
std::string m_new_unit_string;
|
||||||
Vec3d m_new_position;
|
Vec3d m_new_position;
|
||||||
Vec3d m_new_rotation;
|
Vec3d m_new_rotation;
|
||||||
|
Vec3d m_new_absolute_rotation;
|
||||||
Vec3d m_new_scale;
|
Vec3d m_new_scale;
|
||||||
Vec3d m_new_size;
|
Vec3d m_new_size;
|
||||||
|
Vec3d m_unscale_size;
|
||||||
Vec3d m_buffered_position;
|
Vec3d m_buffered_position;
|
||||||
Vec3d m_buffered_rotation;
|
Vec3d m_buffered_rotation;
|
||||||
|
Vec3d m_buffered_absolute_rotation;
|
||||||
Vec3d m_buffered_scale;
|
Vec3d m_buffered_scale;
|
||||||
Vec3d m_buffered_size;
|
Vec3d m_buffered_size;
|
||||||
|
Vec3d cs_center;
|
||||||
bool m_new_enabled {true};
|
bool m_new_enabled {true};
|
||||||
bool m_uniform_scale {true};
|
bool m_uniform_scale {true};
|
||||||
ECoordinatesType m_coordinates_type{ ECoordinatesType::World };
|
// Does the object manipulation panel work in World or Local coordinates?
|
||||||
|
ECoordinatesType m_coordinates_type{ECoordinatesType::World};
|
||||||
|
|
||||||
|
bool m_show_reset_0_rotation{false};
|
||||||
bool m_show_clear_rotation { false };
|
bool m_show_clear_rotation { false };
|
||||||
bool m_show_clear_scale { false };
|
bool m_show_clear_scale { false };
|
||||||
bool m_show_drop_to_bed { false };
|
bool m_show_drop_to_bed { false };
|
||||||
|
enum class RotateType { None, Relative, Absolute
|
||||||
|
};
|
||||||
|
RotateType m_last_rotate_type{RotateType::None}; // 0:no input 1:relative 2:absolute
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float last_move_input_window_width = 0.0f;
|
float last_move_input_window_width = 0.0f;
|
||||||
|
@ -108,21 +120,33 @@ public:
|
||||||
|
|
||||||
void set_uniform_scaling(const bool uniform_scale);
|
void set_uniform_scaling(const bool uniform_scale);
|
||||||
bool get_uniform_scaling() const { return m_uniform_scale; }
|
bool get_uniform_scaling() const { return m_uniform_scale; }
|
||||||
|
void set_use_object_cs(bool flag){ if (m_use_object_cs != flag) m_use_object_cs = flag; }
|
||||||
|
bool get_use_object_cs() { return m_use_object_cs; }
|
||||||
|
// Does the object manipulation panel work in World or Local coordinates?
|
||||||
|
void set_coordinates_type(ECoordinatesType type);
|
||||||
|
ECoordinatesType get_coordinates_type() const { return m_coordinates_type; }
|
||||||
|
bool is_world_coordinates() const { return m_coordinates_type == ECoordinatesType::World; }
|
||||||
|
bool is_instance_coordinates() const { return m_coordinates_type == ECoordinatesType::Instance; }
|
||||||
|
bool is_local_coordinates() const { return m_coordinates_type == ECoordinatesType::Local; }
|
||||||
|
|
||||||
void set_coordinates_type(ECoordinatesType type);
|
const Cache& get_cache() {return m_cache; }
|
||||||
ECoordinatesType get_coordinates_type() const;
|
|
||||||
bool is_world_coordinates() const { return m_coordinates_type == ECoordinatesType::World; }
|
|
||||||
bool is_instance_coordinates() const { return m_coordinates_type == ECoordinatesType::Instance; }
|
|
||||||
bool is_local_coordinates() const { return m_coordinates_type == ECoordinatesType::Local; }
|
|
||||||
|
|
||||||
void reset_cache() { m_cache.reset(); }
|
void reset_cache() { m_cache.reset(); }
|
||||||
|
|
||||||
|
void limit_scaling_ratio(Vec3d &scaling_factor) const;
|
||||||
void on_change(const std::string& opt_key, int axis, double new_value);
|
void on_change(const std::string& opt_key, int axis, double new_value);
|
||||||
|
bool render_combo(ImGuiWrapper *imgui_wrapper, const std::string &label, const std::vector<std::string> &lines, size_t &selection_idx, float label_width, float item_width);
|
||||||
void do_render_move_window(ImGuiWrapper *imgui_wrapper, std::string window_name, float x, float y, float bottom_limit);
|
void do_render_move_window(ImGuiWrapper *imgui_wrapper, std::string window_name, float x, float y, float bottom_limit);
|
||||||
void do_render_rotate_window(ImGuiWrapper *imgui_wrapper, std::string window_name, float x, float y, float bottom_limit);
|
void do_render_rotate_window(ImGuiWrapper *imgui_wrapper, std::string window_name, float x, float y, float bottom_limit);
|
||||||
void do_render_scale_input_window(ImGuiWrapper* imgui_wrapper, std::string window_name, float x, float y, float bottom_limit);
|
void do_render_scale_input_window(ImGuiWrapper* imgui_wrapper, std::string window_name, float x, float y, float bottom_limit);
|
||||||
float max_unit_size(int number, Vec3d &vec1, Vec3d &vec2,std::string str);
|
float max_unit_size(int number, Vec3d &vec1, Vec3d &vec2,std::string str);
|
||||||
bool reset_button(ImGuiWrapper *imgui_wrapper, float caption_max, float unit_size, float space_size, float end_text_size);
|
bool reset_button(ImGuiWrapper *imgui_wrapper, float caption_max, float unit_size, float space_size, float end_text_size);
|
||||||
|
bool reset_zero_button(ImGuiWrapper *imgui_wrapper, float caption_max, float unit_size, float space_size, float end_text_size);
|
||||||
|
bool bbl_checkbox(const wxString &label, bool &value);
|
||||||
|
|
||||||
|
void show_move_tooltip_information(ImGuiWrapper *imgui_wrapper, float caption_max, float x, float y);
|
||||||
|
void show_rotate_tooltip_information(ImGuiWrapper *imgui_wrapper, float caption_max, float x, float y);
|
||||||
|
void show_scale_tooltip_information(ImGuiWrapper *imgui_wrapper, float caption_max, float x, float y);
|
||||||
|
void set_init_rotation(const Geometry::Transformation &value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reset_settings_value();
|
void reset_settings_value();
|
||||||
|
@ -134,18 +158,24 @@ private:
|
||||||
//Show or hide mirror buttons
|
//Show or hide mirror buttons
|
||||||
//void update_mirror_buttons_visibility();
|
//void update_mirror_buttons_visibility();
|
||||||
|
|
||||||
// change values
|
// change values
|
||||||
void change_position_value(int axis, double value);
|
void change_position_value(int axis, double value);
|
||||||
void change_rotation_value(int axis, double value);
|
void change_rotation_value(int axis, double value);
|
||||||
|
void change_absolute_rotation_value(int axis, double value);
|
||||||
void change_scale_value(int axis, double value);
|
void change_scale_value(int axis, double value);
|
||||||
void change_size_value(int axis, double value);
|
void change_size_value(int axis, double value);
|
||||||
void do_scale(int axis, const Vec3d &scale) const;
|
void do_scale(int axis, const Vec3d &scale) const;
|
||||||
void reset_position_value();
|
void reset_position_value();
|
||||||
void reset_rotation_value();
|
void reset_rotation_value(bool reset_relative);
|
||||||
void reset_scale_value();
|
void reset_scale_value();
|
||||||
|
|
||||||
GLCanvas3D& m_glcanvas;
|
GLCanvas3D& m_glcanvas;
|
||||||
unsigned int m_last_active_item { 0 };
|
unsigned int m_last_active_item { 0 };
|
||||||
|
std::map<std::string, wxString> m_desc_move;
|
||||||
|
std::map<std::string, wxString> m_desc_rotate;
|
||||||
|
std::map<std::string, wxString> m_desc_scale;
|
||||||
|
Vec3d m_init_rotation;
|
||||||
|
Transform3d m_init_rotation_scale_tran;
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -401,6 +401,39 @@ void Selection::remove_volumes(EMode mode, const std::vector<unsigned int>& volu
|
||||||
this->set_bounding_boxes_dirty();
|
this->set_bounding_boxes_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelVolume *Selection::get_selected_single_volume(int &out_object_idx, int &out_volume_idx) const
|
||||||
|
{
|
||||||
|
if (is_single_volume() || is_single_modifier()) {
|
||||||
|
const GLVolume *gl_volume = get_first_volume();
|
||||||
|
out_object_idx = gl_volume->object_idx();
|
||||||
|
ModelObject *model_object = get_model()->objects[out_object_idx];
|
||||||
|
out_volume_idx = gl_volume->volume_idx();
|
||||||
|
if (out_volume_idx < model_object->volumes.size())
|
||||||
|
return model_object->volumes[out_volume_idx];
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelObject *Selection::get_selected_single_object(int &out_object_idx) const
|
||||||
|
{
|
||||||
|
if (is_single_volume() || is_single_modifier() || is_single_full_object()) {
|
||||||
|
const GLVolume *gl_volume = get_first_volume();
|
||||||
|
out_object_idx = gl_volume->object_idx();
|
||||||
|
return get_model()->objects[out_object_idx];
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ModelInstance *Selection::get_selected_single_intance() const
|
||||||
|
{
|
||||||
|
int object_idx;
|
||||||
|
auto mo = get_selected_single_object(object_idx);
|
||||||
|
if (mo) {
|
||||||
|
return mo->instances[get_instance_idx()];
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void Selection::add_curr_plate()
|
void Selection::add_curr_plate()
|
||||||
{
|
{
|
||||||
if (!m_valid)
|
if (!m_valid)
|
||||||
|
@ -910,17 +943,17 @@ const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const
|
||||||
return *m_scaled_instance_bounding_box;
|
return *m_scaled_instance_bounding_box;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BoundingBoxf3& Selection::get_full_unscaled_instance_bounding_box() const
|
const BoundingBoxf3 &Selection::get_full_unscaled_instance_bounding_box() const
|
||||||
{
|
{
|
||||||
assert(is_single_full_instance());
|
assert(is_single_full_instance());
|
||||||
|
|
||||||
if (!m_full_unscaled_instance_bounding_box.has_value()) {
|
if (!m_full_unscaled_instance_bounding_box.has_value()) {
|
||||||
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_full_unscaled_instance_bounding_box);
|
std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_unscaled_instance_bounding_box);
|
||||||
*bbox = BoundingBoxf3();
|
*bbox = BoundingBoxf3();
|
||||||
if (m_valid) {
|
if (m_valid) {
|
||||||
for (unsigned int i : m_list) {
|
for (unsigned int i : m_list) {
|
||||||
const GLVolume& volume = *(*m_volumes)[i];
|
const GLVolume &volume = *(*m_volumes)[i];
|
||||||
Transform3d trafo = volume.get_instance_transformation().get_matrix_no_scaling_factor() * volume.get_volume_transformation().get_matrix();
|
Transform3d trafo = volume.get_instance_transformation().get_matrix_no_scaling_factor() * volume.get_volume_transformation().get_matrix();
|
||||||
trafo.translation().z() += volume.get_sla_shift_z();
|
trafo.translation().z() += volume.get_sla_shift_z();
|
||||||
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
|
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
|
||||||
}
|
}
|
||||||
|
@ -929,17 +962,17 @@ const BoundingBoxf3& Selection::get_full_unscaled_instance_bounding_box() const
|
||||||
return *m_full_unscaled_instance_bounding_box;
|
return *m_full_unscaled_instance_bounding_box;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BoundingBoxf3& Selection::get_full_scaled_instance_bounding_box() const
|
const BoundingBoxf3 &Selection::get_full_scaled_instance_bounding_box() const
|
||||||
{
|
{
|
||||||
assert(is_single_full_instance());
|
assert(is_single_full_instance());
|
||||||
|
|
||||||
if (!m_full_scaled_instance_bounding_box.has_value()) {
|
if (!m_full_scaled_instance_bounding_box.has_value()) {
|
||||||
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_full_scaled_instance_bounding_box);
|
std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_scaled_instance_bounding_box);
|
||||||
*bbox = BoundingBoxf3();
|
*bbox = BoundingBoxf3();
|
||||||
if (m_valid) {
|
if (m_valid) {
|
||||||
for (unsigned int i : m_list) {
|
for (unsigned int i : m_list) {
|
||||||
const GLVolume& volume = *(*m_volumes)[i];
|
const GLVolume &volume = *(*m_volumes)[i];
|
||||||
Transform3d trafo = volume.get_instance_transformation().get_matrix() * volume.get_volume_transformation().get_matrix();
|
Transform3d trafo = volume.get_instance_transformation().get_matrix() * volume.get_volume_transformation().get_matrix();
|
||||||
trafo.translation().z() += volume.get_sla_shift_z();
|
trafo.translation().z() += volume.get_sla_shift_z();
|
||||||
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
|
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
|
||||||
}
|
}
|
||||||
|
@ -948,17 +981,17 @@ const BoundingBoxf3& Selection::get_full_scaled_instance_bounding_box() const
|
||||||
return *m_full_scaled_instance_bounding_box;
|
return *m_full_scaled_instance_bounding_box;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BoundingBoxf3& Selection::get_full_unscaled_instance_local_bounding_box() const
|
const BoundingBoxf3 &Selection::get_full_unscaled_instance_local_bounding_box() const
|
||||||
{
|
{
|
||||||
assert(is_single_full_instance());
|
assert(is_single_full_instance());
|
||||||
|
|
||||||
if (!m_full_unscaled_instance_local_bounding_box.has_value()) {
|
if (!m_full_unscaled_instance_local_bounding_box.has_value()) {
|
||||||
std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_full_unscaled_instance_local_bounding_box);
|
std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_unscaled_instance_local_bounding_box);
|
||||||
*bbox = BoundingBoxf3();
|
*bbox = BoundingBoxf3();
|
||||||
if (m_valid) {
|
if (m_valid) {
|
||||||
for (unsigned int i : m_list) {
|
for (unsigned int i : m_list) {
|
||||||
const GLVolume& volume = *(*m_volumes)[i];
|
const GLVolume &volume = *(*m_volumes)[i];
|
||||||
Transform3d trafo = volume.get_volume_transformation().get_matrix();
|
Transform3d trafo = volume.get_volume_transformation().get_matrix();
|
||||||
trafo.translation().z() += volume.get_sla_shift_z();
|
trafo.translation().z() += volume.get_sla_shift_z();
|
||||||
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
|
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
|
||||||
}
|
}
|
||||||
|
@ -967,22 +1000,20 @@ const BoundingBoxf3& Selection::get_full_unscaled_instance_local_bounding_box()
|
||||||
return *m_full_unscaled_instance_local_bounding_box;
|
return *m_full_unscaled_instance_local_bounding_box;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::pair<BoundingBoxf3, Transform3d>& Selection::get_bounding_box_in_current_reference_system() const
|
const std::pair<BoundingBoxf3, Transform3d> &Selection::get_bounding_box_in_current_reference_system() const
|
||||||
{
|
{
|
||||||
static int last_coordinates_type = -1;
|
static int last_coordinates_type = -1;
|
||||||
|
|
||||||
assert(!is_empty());
|
assert(!is_empty());
|
||||||
|
|
||||||
ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
|
ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
|
||||||
if (m_mode == Instance && coordinates_type == ECoordinatesType::Local)
|
if (m_mode == Instance && coordinates_type == ECoordinatesType::Local) coordinates_type = ECoordinatesType::World;
|
||||||
coordinates_type = ECoordinatesType::World;
|
|
||||||
|
|
||||||
if (last_coordinates_type != int(coordinates_type))
|
if (last_coordinates_type != int(coordinates_type)) const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>> *>(&m_bounding_box_in_current_reference_system)->reset();
|
||||||
const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>>*>(&m_bounding_box_in_current_reference_system)->reset();
|
|
||||||
|
|
||||||
if (!m_bounding_box_in_current_reference_system.has_value()) {
|
if (!m_bounding_box_in_current_reference_system.has_value()) {
|
||||||
last_coordinates_type = int(coordinates_type);
|
last_coordinates_type = int(coordinates_type);
|
||||||
*const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>>*>(&m_bounding_box_in_current_reference_system) = get_bounding_box_in_reference_system(coordinates_type);
|
*const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>> *>(&m_bounding_box_in_current_reference_system) = get_bounding_box_in_reference_system(coordinates_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *m_bounding_box_in_current_reference_system;
|
return *m_bounding_box_in_current_reference_system;
|
||||||
|
@ -994,11 +1025,19 @@ std::pair<BoundingBoxf3, Transform3d> Selection::get_bounding_box_in_reference_s
|
||||||
// trafo to current reference system
|
// trafo to current reference system
|
||||||
//
|
//
|
||||||
Transform3d trafo;
|
Transform3d trafo;
|
||||||
switch (type)
|
switch (type) {
|
||||||
{
|
case ECoordinatesType::World: {
|
||||||
case ECoordinatesType::World: { trafo = Transform3d::Identity(); break; }
|
trafo = Transform3d::Identity();
|
||||||
case ECoordinatesType::Instance: { trafo = get_first_volume()->get_instance_transformation().get_matrix(); break; }
|
break;
|
||||||
case ECoordinatesType::Local: { trafo = get_first_volume()->world_matrix(); break; }
|
}
|
||||||
|
case ECoordinatesType::Instance: {
|
||||||
|
trafo = get_first_volume()->get_instance_transformation().get_matrix();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ECoordinatesType::Local: {
|
||||||
|
trafo = get_first_volume()->world_matrix();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1006,60 +1045,55 @@ std::pair<BoundingBoxf3, Transform3d> Selection::get_bounding_box_in_reference_s
|
||||||
//
|
//
|
||||||
Geometry::Transformation t(trafo);
|
Geometry::Transformation t(trafo);
|
||||||
t.reset_scaling_factor();
|
t.reset_scaling_factor();
|
||||||
const Transform3d basis_trafo = t.get_matrix_no_offset();
|
const Transform3d basis_trafo = t.get_matrix_no_offset();
|
||||||
std::vector<Vec3d> axes = { Vec3d::UnitX(), Vec3d::UnitY(), Vec3d::UnitZ() };
|
std::vector<Vec3d> axes = {Vec3d::UnitX(), Vec3d::UnitY(), Vec3d::UnitZ()};
|
||||||
for (size_t i = 0; i < axes.size(); ++i) {
|
for (size_t i = 0; i < axes.size(); ++i) { axes[i] = basis_trafo * axes[i]; }
|
||||||
axes[i] = basis_trafo * axes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// calculate bounding box aligned to trafo basis
|
// calculate bounding box aligned to trafo basis
|
||||||
//
|
//
|
||||||
Vec3d min = { DBL_MAX, DBL_MAX, DBL_MAX };
|
Vec3d min = {DBL_MAX, DBL_MAX, DBL_MAX};
|
||||||
Vec3d max = { -DBL_MAX, -DBL_MAX, -DBL_MAX };
|
Vec3d max = {-DBL_MAX, -DBL_MAX, -DBL_MAX};
|
||||||
for (unsigned int id : m_list) {
|
for (unsigned int id : m_list) {
|
||||||
const GLVolume& vol = *get_volume(id);
|
const GLVolume & vol = *get_volume(id);
|
||||||
const Transform3d vol_world_rafo = vol.world_matrix();
|
const Transform3d vol_world_rafo = vol.world_matrix();
|
||||||
const TriangleMesh* mesh = vol.convex_hull();
|
const TriangleMesh *mesh = vol.convex_hull();
|
||||||
if (mesh == nullptr)
|
if (mesh == nullptr)
|
||||||
mesh = &m_model->objects[vol.object_idx()]->volumes[vol.volume_idx()]->mesh();
|
mesh = &m_model->objects[vol.object_idx()]->volumes[vol.volume_idx()]->mesh();
|
||||||
assert(mesh != nullptr);
|
assert(mesh != nullptr);
|
||||||
for (const stl_vertex& v : mesh->its.vertices) {
|
for (const stl_vertex &v : mesh->its.vertices) {
|
||||||
const Vec3d world_v = vol_world_rafo * v.cast<double>();
|
const Vec3d world_v = vol_world_rafo * v.cast<double>();
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
const double i_comp = world_v.dot(axes[i]);
|
const double i_comp = world_v.dot(axes[i]);
|
||||||
min(i) = std::min(min(i), i_comp);
|
min(i) = std::min(min(i), i_comp);
|
||||||
max(i) = std::max(max(i), i_comp);
|
max(i) = std::max(max(i), i_comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Vec3d box_size = max - min;
|
const Vec3d box_size = max - min;
|
||||||
Vec3d half_box_size = 0.5 * box_size;
|
Vec3d half_box_size = 0.5 * box_size;
|
||||||
Geometry::Transformation out_trafo(trafo);
|
Geometry::Transformation out_trafo(trafo);
|
||||||
Vec3d center = 0.5 * (min + max);
|
Vec3d center = 0.5 * (min + max);
|
||||||
|
|
||||||
// Fix for non centered volume
|
// Fix for non centered volume
|
||||||
// by move with calculated center(to volume center) and extend half box size
|
// by move with calculated center(to volume center) and extend half box size
|
||||||
// e.g. for right aligned embossed text
|
// e.g. for right aligned embossed text
|
||||||
if (m_list.size() == 1 &&
|
if (m_list.size() == 1 && type == ECoordinatesType::Local) {
|
||||||
type == ECoordinatesType::Local) {
|
const GLVolume & vol = *get_volume(*m_list.begin());
|
||||||
const GLVolume& vol = *get_volume(*m_list.begin());
|
|
||||||
const Transform3d vol_world_trafo = vol.world_matrix();
|
const Transform3d vol_world_trafo = vol.world_matrix();
|
||||||
Vec3d world_zero = vol_world_trafo * Vec3d::Zero();
|
Vec3d world_zero = vol_world_trafo * Vec3d::Zero();
|
||||||
for (size_t i = 0; i < 3; i++){
|
for (size_t i = 0; i < 3; i++) {
|
||||||
// move center to local volume zero
|
// move center to local volume zero
|
||||||
center[i] = world_zero.dot(axes[i]);
|
center[i] = world_zero.dot(axes[i]);
|
||||||
// extend half size to bigger distance from center
|
// extend half size to bigger distance from center
|
||||||
half_box_size[i] = std::max(
|
half_box_size[i] = std::max(abs(center[i] - min[i]), abs(center[i] - max[i]));
|
||||||
abs(center[i] - min[i]),
|
|
||||||
abs(center[i] - max[i]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const BoundingBoxf3 out_box(-half_box_size, half_box_size);
|
const BoundingBoxf3 out_box(-half_box_size, half_box_size);
|
||||||
out_trafo.set_offset(basis_trafo * center);
|
out_trafo.set_offset(basis_trafo * center);
|
||||||
return { out_box, out_trafo.get_matrix_no_scaling_factor() };
|
return {out_box, out_trafo.get_matrix_no_scaling_factor()};
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::pair<Vec3d, double> Selection::get_bounding_sphere() const
|
const std::pair<Vec3d, double> Selection::get_bounding_sphere() const
|
||||||
|
@ -1138,34 +1172,52 @@ void Selection::move_to_center(const Vec3d& displacement, bool local)
|
||||||
this->set_bounding_boxes_dirty();
|
this->set_bounding_boxes_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Selection::translate(const Vec3d& displacement, TransformationType transformation_type)
|
void Selection::translate(const Vec3d &displacement, TransformationType transformation_type)
|
||||||
{
|
{
|
||||||
if (!m_valid)
|
if (!m_valid) return;
|
||||||
return;
|
|
||||||
|
|
||||||
// Emboss use translate in local coordinate
|
|
||||||
assert(transformation_type.relative() ||
|
|
||||||
transformation_type.local());
|
|
||||||
|
|
||||||
for (unsigned int i : m_list) {
|
for (unsigned int i : m_list) {
|
||||||
GLVolume& v = *(*m_volumes)[i];
|
GLVolume & v = *(*m_volumes)[i];
|
||||||
const VolumeCache& volume_data = m_cache.volumes_data[i];
|
const VolumeCache &volume_data = m_cache.volumes_data[i];
|
||||||
if (m_mode == Instance && !is_wipe_tower()) {
|
if (m_mode == Instance && !is_wipe_tower()) {
|
||||||
assert(is_from_fully_selected_instance(i));
|
assert(is_from_fully_selected_instance(i));
|
||||||
if (transformation_type.instance()) {
|
if (transformation_type.instance()) {
|
||||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
|
||||||
v.set_instance_offset(inst_trafo.get_offset() + inst_trafo.get_rotation_matrix() * displacement);
|
v.set_instance_offset(inst_trafo.get_offset() + inst_trafo.get_rotation_matrix() * displacement);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center);
|
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center);
|
||||||
}
|
} else {
|
||||||
else {
|
if (v.is_wipe_tower) {//in world cs
|
||||||
if (transformation_type.local() && transformation_type.absolute()) {
|
int plate_idx = v.object_idx() - 1000;
|
||||||
const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform();
|
BoundingBoxf3 plate_bbox = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx)->get_bounding_box();
|
||||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
Vec3d tower_size = v.bounding_box().size();
|
||||||
v.set_volume_offset(vol_trafo.get_offset() + inst_trafo.get_scaling_factor_matrix().inverse() * vol_trafo.get_rotation_matrix() * displacement);
|
Vec3d tower_origin = m_cache.volumes_data[i].get_volume_position();
|
||||||
|
Vec3d actual_displacement = displacement;
|
||||||
|
const double margin = WIPE_TOWER_MARGIN;
|
||||||
|
|
||||||
|
actual_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() *
|
||||||
|
m_cache.volumes_data[i].get_instance_mirror_matrix())
|
||||||
|
.inverse() *
|
||||||
|
displacement;
|
||||||
|
if (tower_origin(0) + actual_displacement(0) - margin < plate_bbox.min(0)) {
|
||||||
|
actual_displacement(0) = plate_bbox.min(0) - tower_origin(0) + margin;
|
||||||
|
} else if (tower_origin(0) + actual_displacement(0) + tower_size(0) + margin > plate_bbox.max(0)) {
|
||||||
|
actual_displacement(0) = plate_bbox.max(0) - tower_origin(0) - tower_size(0) - margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tower_origin(1) + actual_displacement(1) - margin < plate_bbox.min(1)) {
|
||||||
|
actual_displacement(1) = plate_bbox.min(1) - tower_origin(1) + margin;
|
||||||
|
} else if (tower_origin(1) + actual_displacement(1) + tower_size(1) + margin > plate_bbox.max(1)) {
|
||||||
|
actual_displacement(1) = plate_bbox.max(1) - tower_origin(1) - tower_size(1) - margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + actual_displacement);
|
||||||
}
|
}
|
||||||
else {
|
else if (transformation_type.local() && transformation_type.absolute()) {
|
||||||
|
const Geometry::Transformation &vol_trafo = volume_data.get_volume_transform();
|
||||||
|
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
|
||||||
|
v.set_volume_offset(vol_trafo.get_offset() + inst_trafo.get_scaling_factor_matrix().inverse() * vol_trafo.get_rotation_matrix() * displacement);
|
||||||
|
} else {
|
||||||
Vec3d relative_disp = displacement;
|
Vec3d relative_disp = displacement;
|
||||||
if (transformation_type.world() && transformation_type.instance())
|
if (transformation_type.world() && transformation_type.instance())
|
||||||
relative_disp = volume_data.get_instance_transform().get_scaling_factor_matrix().inverse() * relative_disp;
|
relative_disp = volume_data.get_instance_transform().get_scaling_factor_matrix().inverse() * relative_disp;
|
||||||
|
@ -1181,12 +1233,14 @@ void Selection::translate(const Vec3d& displacement, TransformationType transfor
|
||||||
else if (m_mode == Volume)
|
else if (m_mode == Volume)
|
||||||
synchronize_unselected_volumes();
|
synchronize_unselected_volumes();
|
||||||
#endif // !DISABLE_INSTANCES_SYNCH
|
#endif // !DISABLE_INSTANCES_SYNCH
|
||||||
|
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||||
ensure_not_below_bed();
|
ensure_not_below_bed();
|
||||||
|
}
|
||||||
set_bounding_boxes_dirty();
|
set_bounding_boxes_dirty();
|
||||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||||
|
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
|
// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
|
||||||
void Selection::rotate(const Vec3d& rotation, TransformationType transformation_type)
|
void Selection::rotate(const Vec3d& rotation, TransformationType transformation_type)
|
||||||
{
|
{
|
||||||
|
@ -1287,7 +1341,9 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
||||||
#endif // !DISABLE_INSTANCES_SYNCH
|
#endif // !DISABLE_INSTANCES_SYNCH
|
||||||
|
|
||||||
set_bounding_boxes_dirty();
|
set_bounding_boxes_dirty();
|
||||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||||
|
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Selection::flattening_rotate(const Vec3d& normal)
|
void Selection::flattening_rotate(const Vec3d& normal)
|
||||||
|
@ -1320,96 +1376,6 @@ void Selection::flattening_rotate(const Vec3d& normal)
|
||||||
this->set_bounding_boxes_dirty();
|
this->set_bounding_boxes_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Selection::scale_legacy(const Vec3d& scale, TransformationType transformation_type)
|
|
||||||
{
|
|
||||||
if (!m_valid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (unsigned int i : m_list) {
|
|
||||||
GLVolume &v = *(*m_volumes)[i];
|
|
||||||
if (is_single_full_instance()) {
|
|
||||||
if (transformation_type.relative()) {
|
|
||||||
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
|
|
||||||
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
|
|
||||||
// extracts scaling factors from the composed transformation
|
|
||||||
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
|
||||||
if (transformation_type.joint())
|
|
||||||
v.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
|
||||||
|
|
||||||
v.set_instance_scaling_factor(new_scale);
|
|
||||||
// Restore mirror state
|
|
||||||
v.set_instance_mirror(m_cache.volumes_data[i].get_instance_transform().get_mirror());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const auto mirror = v.get_instance_mirror();
|
|
||||||
if (transformation_type.world() && (std::abs(scale.x() - scale.y()) > EPSILON || std::abs(scale.x() - scale.z()) > EPSILON)) {
|
|
||||||
// Non-uniform scaling. Transform the scaling factors into the local coordinate system.
|
|
||||||
// This is only possible, if the instance rotation is mulitples of ninety degrees.
|
|
||||||
assert(Geometry::is_rotation_ninety_degrees(v.get_instance_rotation()));
|
|
||||||
v.set_instance_scaling_factor((v.get_instance_transformation().get_rotation_matrix().matrix().block<3, 3>(0, 0).transpose() * scale).cwiseAbs());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
v.set_instance_scaling_factor(scale);
|
|
||||||
// Restore mirror state
|
|
||||||
v.set_instance_mirror(mirror);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the instance assemble transform
|
|
||||||
ModelObject* object = m_model->objects[v.object_idx()];
|
|
||||||
Geometry::Transformation assemble_transform = object->instances[v.instance_idx()]->get_assemble_transformation();
|
|
||||||
const auto mirror = assemble_transform.get_mirror();
|
|
||||||
assemble_transform.set_scaling_factor(v.get_instance_scaling_factor());
|
|
||||||
assemble_transform.set_mirror(mirror);
|
|
||||||
object->instances[v.instance_idx()]->set_assemble_transformation(assemble_transform);
|
|
||||||
}
|
|
||||||
else if (is_single_volume() || is_single_modifier()) {
|
|
||||||
const auto mirror = v.get_volume_transformation().get_mirror();
|
|
||||||
v.set_volume_scaling_factor(scale);
|
|
||||||
// Restore mirror state
|
|
||||||
v.set_volume_mirror(mirror);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
|
|
||||||
if (m_mode == Instance) {
|
|
||||||
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
|
|
||||||
// extracts scaling factors from the composed transformation
|
|
||||||
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
|
||||||
if (transformation_type.joint())
|
|
||||||
v.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
|
||||||
|
|
||||||
v.set_instance_scaling_factor(new_scale);
|
|
||||||
// Restore mirror state
|
|
||||||
v.set_instance_mirror(m_cache.volumes_data[i].get_instance_transform().get_mirror());
|
|
||||||
}
|
|
||||||
else if (m_mode == Volume) {
|
|
||||||
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3);
|
|
||||||
// extracts scaling factors from the composed transformation
|
|
||||||
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
|
||||||
if (transformation_type.joint()) {
|
|
||||||
Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
|
|
||||||
v.set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset);
|
|
||||||
}
|
|
||||||
v.set_volume_scaling_factor(new_scale);
|
|
||||||
// Restore mirror state
|
|
||||||
v.set_volume_mirror(m_cache.volumes_data[i].get_volume_transform().get_mirror());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !DISABLE_INSTANCES_SYNCH
|
|
||||||
if (m_mode == Instance)
|
|
||||||
// even if there is no rotation, we pass SyncRotationType::GENERAL to force
|
|
||||||
// synchronize_unselected_instances() to apply the scale to the other instances
|
|
||||||
synchronize_unselected_instances(SyncRotationType::GENERAL);
|
|
||||||
else if (m_mode == Volume)
|
|
||||||
synchronize_unselected_volumes();
|
|
||||||
#endif // !DISABLE_INSTANCES_SYNCH
|
|
||||||
|
|
||||||
ensure_on_bed();
|
|
||||||
set_bounding_boxes_dirty();
|
|
||||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Selection::scale(const Vec3d& scale, TransformationType transformation_type)
|
void Selection::scale(const Vec3d& scale, TransformationType transformation_type)
|
||||||
{
|
{
|
||||||
scale_and_translate(scale, Vec3d::Zero(), transformation_type);
|
scale_and_translate(scale, Vec3d::Zero(), transformation_type);
|
||||||
|
@ -1552,16 +1518,9 @@ void Selection::scale_to_fit_print_volume(const DynamicPrintConfig& config)
|
||||||
}
|
}
|
||||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||||
|
|
||||||
void Selection::mirror(Axis axis, TransformationType transformation_type)
|
void Selection::scale_and_translate(const Vec3d &scale, const Vec3d &world_translation, TransformationType transformation_type)
|
||||||
{
|
{
|
||||||
const Vec3d mirror((axis == X) ? -1.0 : 1.0, (axis == Y) ? -1.0 : 1.0, (axis == Z) ? -1.0 : 1.0);
|
if (!m_valid) return;
|
||||||
scale_and_translate(mirror, Vec3d::Zero(), transformation_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& world_translation, TransformationType transformation_type)
|
|
||||||
{
|
|
||||||
if (!m_valid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Vec3d relative_scale = scale;
|
Vec3d relative_scale = scale;
|
||||||
if (transformation_type.absolute()) {
|
if (transformation_type.absolute()) {
|
||||||
|
@ -1582,45 +1541,52 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& world_trans
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i : m_list) {
|
for (unsigned int i : m_list) {
|
||||||
GLVolume& v = *(*m_volumes)[i];
|
GLVolume & v = *(*m_volumes)[i];
|
||||||
const VolumeCache& volume_data = m_cache.volumes_data[i];
|
const VolumeCache & volume_data = m_cache.volumes_data[i];
|
||||||
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
|
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
|
||||||
|
|
||||||
if (m_mode == Instance) {
|
if (m_mode == Instance) {
|
||||||
if (transformation_type.instance()) {
|
if (transformation_type.instance()) {
|
||||||
const Vec3d world_inst_pivot = m_cache.dragging_center - inst_trafo.get_offset();
|
const Vec3d world_inst_pivot = m_cache.dragging_center - inst_trafo.get_offset();
|
||||||
const Vec3d local_inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * world_inst_pivot;
|
const Vec3d local_inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * world_inst_pivot;
|
||||||
Matrix3d inst_rotation, inst_scale;
|
Matrix3d inst_rotation, inst_scale;
|
||||||
inst_trafo.get_matrix().computeRotationScaling(&inst_rotation, &inst_scale);
|
inst_trafo.get_matrix().computeRotationScaling(&inst_rotation, &inst_scale);
|
||||||
const Transform3d offset_trafo = Geometry::translation_transform(inst_trafo.get_offset() + world_translation);
|
const Transform3d offset_trafo = Geometry::translation_transform(inst_trafo.get_offset() + world_translation);
|
||||||
const Transform3d scale_trafo = Transform3d(inst_scale) * Geometry::scale_transform(relative_scale);
|
const Transform3d scale_trafo = Transform3d(inst_scale) * Geometry::scale_transform(relative_scale);
|
||||||
v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * offset_trafo * Transform3d(inst_rotation) * scale_trafo * Geometry::translation_transform(-local_inst_pivot));
|
v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * offset_trafo * Transform3d(inst_rotation) * scale_trafo *
|
||||||
}
|
Geometry::translation_transform(-local_inst_pivot));
|
||||||
else
|
} else
|
||||||
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center);
|
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(relative_scale),
|
||||||
}
|
m_cache.dragging_center);
|
||||||
else {
|
// update the instance assemble transform
|
||||||
|
ModelObject * object = m_model->objects[v.object_idx()];
|
||||||
|
Geometry::Transformation assemble_transform = object->instances[v.instance_idx()]->get_assemble_transformation();
|
||||||
|
assemble_transform.set_scaling_factor(v.get_instance_scaling_factor());
|
||||||
|
object->instances[v.instance_idx()]->set_assemble_transformation(assemble_transform);
|
||||||
|
} else {
|
||||||
if (!is_single_volume_or_modifier()) {
|
if (!is_single_volume_or_modifier()) {
|
||||||
assert(transformation_type.world());
|
assert(transformation_type.world());
|
||||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(scale), m_cache.dragging_center);
|
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(scale),
|
||||||
}
|
m_cache.dragging_center);
|
||||||
else {
|
} else {
|
||||||
transformation_type.set_independent();
|
transformation_type.set_independent();
|
||||||
Vec3d translation;
|
Vec3d translation;
|
||||||
if (transformation_type.local())
|
if (transformation_type.local()) {
|
||||||
translation = volume_data.get_volume_transform().get_matrix_no_offset().inverse() * inst_trafo.get_matrix_no_offset().inverse() * world_translation;
|
translation = volume_data.get_volume_transform().get_matrix_no_offset().inverse() * inst_trafo.get_matrix_no_offset().inverse() * world_translation;
|
||||||
|
}
|
||||||
else if (transformation_type.instance())
|
else if (transformation_type.instance())
|
||||||
translation = inst_trafo.get_matrix_no_offset().inverse() * world_translation;
|
translation = inst_trafo.get_matrix_no_offset().inverse() * world_translation;
|
||||||
else
|
else
|
||||||
translation = world_translation;
|
translation = world_translation;
|
||||||
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(scale), m_cache.dragging_center);
|
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(scale),
|
||||||
|
m_cache.dragging_center);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !DISABLE_INSTANCES_SYNCH
|
#if !DISABLE_INSTANCES_SYNCH
|
||||||
if (m_mode == Instance)
|
if (m_mode == Instance)
|
||||||
// even if there is no rotation, we pass SyncRotationType::GENERAL to force
|
// even if there is no rotation, we pass SyncRotationType::GENERAL to force
|
||||||
// synchronize_unselected_instances() to apply the scale to the other instances
|
// synchronize_unselected_instances() to apply the scale to the other instances
|
||||||
synchronize_unselected_instances(SyncRotationType::GENERAL);
|
synchronize_unselected_instances(SyncRotationType::GENERAL);
|
||||||
else if (m_mode == Volume)
|
else if (m_mode == Volume)
|
||||||
|
@ -1629,7 +1595,16 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& world_trans
|
||||||
|
|
||||||
ensure_on_bed();
|
ensure_on_bed();
|
||||||
set_bounding_boxes_dirty();
|
set_bounding_boxes_dirty();
|
||||||
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||||
|
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Selection::mirror(Axis axis, TransformationType transformation_type)
|
||||||
|
{
|
||||||
|
const Vec3d mirror((axis == X) ? -1.0 : 1.0, (axis == Y) ? -1.0 : 1.0, (axis == Z) ? -1.0 : 1.0);
|
||||||
|
scale_and_translate(mirror, Vec3d::Zero(), transformation_type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Selection::translate(unsigned int object_idx, const Vec3d& displacement)
|
void Selection::translate(unsigned int object_idx, const Vec3d& displacement)
|
||||||
|
@ -1944,7 +1919,8 @@ void Selection::render(float scale_factor)
|
||||||
m_scale_factor = scale_factor;
|
m_scale_factor = scale_factor;
|
||||||
// render cumulative bounding box of selected volumes
|
// render cumulative bounding box of selected volumes
|
||||||
const auto& [box, trafo] = get_bounding_box_in_current_reference_system();
|
const auto& [box, trafo] = get_bounding_box_in_current_reference_system();
|
||||||
render_bounding_box(box, trafo, ColorRGB::WHITE());
|
render_bounding_box(box, trafo,
|
||||||
|
wxGetApp().plater()->canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasAssembleView ? ColorRGB::YELLOW(): ColorRGB::WHITE());
|
||||||
render_synchronized_volumes();
|
render_synchronized_volumes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1992,40 +1968,33 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif
|
||||||
|
|
||||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
|
|
||||||
const Transform3d base_matrix = Geometry::assemble_transform(get_bounding_box().center());
|
Vec3d center = get_bounding_box().center();
|
||||||
Transform3d orient_matrix = Transform3d::Identity();
|
Transform3d orient_matrix = Transform3d::Identity();
|
||||||
|
|
||||||
if (!boost::starts_with(sidebar_field, "layer")) {
|
if (!boost::starts_with(sidebar_field, "layer")) {
|
||||||
shader->set_uniform("emission_factor", 0.05f);
|
shader->set_uniform("emission_factor", 0.05f);
|
||||||
|
const auto &[box, box_trafo] = get_bounding_box_in_current_reference_system();
|
||||||
// BBS
|
// BBS
|
||||||
if (is_single_full_instance()/* && !wxGetApp().obj_manipul()->get_world_coordinates()*/) {
|
if (is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||||
if (!boost::starts_with(sidebar_field, "position")) {
|
center = box_trafo.translation();
|
||||||
if (boost::starts_with(sidebar_field, "scale"))
|
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
||||||
|
} else if (is_single_volume_or_modifier()) {
|
||||||
|
if (!wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||||
|
if (wxGetApp().obj_manipul()->is_local_coordinates()) {
|
||||||
|
orient_matrix = get_bounding_box_in_current_reference_system().second;
|
||||||
|
orient_matrix.translation() = Vec3d::Zero();
|
||||||
|
} else {
|
||||||
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
||||||
else if (boost::starts_with(sidebar_field, "rotation")) {
|
center = box_trafo.translation();
|
||||||
if (boost::ends_with(sidebar_field, "x"))
|
|
||||||
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
|
||||||
else if (boost::ends_with(sidebar_field, "y")) {
|
|
||||||
const Vec3d& rotation = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation();
|
|
||||||
if (rotation.x() == 0.0)
|
|
||||||
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
|
||||||
else
|
|
||||||
orient_matrix.rotate(Eigen::AngleAxisd(rotation.z(), Vec3d::UnitZ()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else if (is_single_volume() || is_single_modifier()) {
|
if (requires_local_axes()) {
|
||||||
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
|
||||||
if (!boost::starts_with(sidebar_field, "position"))
|
|
||||||
orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_rotation_matrix();
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (requires_local_axes())
|
|
||||||
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const Transform3d base_matrix = Geometry::assemble_transform(center);
|
||||||
|
|
||||||
if (!boost::starts_with(sidebar_field, "layer"))
|
if (!boost::starts_with(sidebar_field, "layer"))
|
||||||
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
|
||||||
|
@ -2033,6 +2002,8 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif
|
||||||
render_sidebar_position_hints(sidebar_field, *shader, base_matrix * orient_matrix);
|
render_sidebar_position_hints(sidebar_field, *shader, base_matrix * orient_matrix);
|
||||||
else if (boost::starts_with(sidebar_field, "rotation"))
|
else if (boost::starts_with(sidebar_field, "rotation"))
|
||||||
render_sidebar_rotation_hints(sidebar_field, *shader, base_matrix * orient_matrix);
|
render_sidebar_rotation_hints(sidebar_field, *shader, base_matrix * orient_matrix);
|
||||||
|
else if (boost::starts_with(sidebar_field, "absolute_rotation"))
|
||||||
|
render_sidebar_rotation_hints(sidebar_field, *shader, base_matrix * orient_matrix);
|
||||||
else if (boost::starts_with(sidebar_field, "scale") || boost::starts_with(sidebar_field, "size"))
|
else if (boost::starts_with(sidebar_field, "scale") || boost::starts_with(sidebar_field, "size"))
|
||||||
//BBS: GUI refactor: add uniform_scale from gizmo
|
//BBS: GUI refactor: add uniform_scale from gizmo
|
||||||
render_sidebar_scale_hints(sidebar_field, uniform_scale, *shader, base_matrix * orient_matrix);
|
render_sidebar_scale_hints(sidebar_field, uniform_scale, *shader, base_matrix * orient_matrix);
|
||||||
|
@ -3052,6 +3023,9 @@ void Selection::ensure_not_below_bed()
|
||||||
|
|
||||||
bool Selection::is_from_fully_selected_instance(unsigned int volume_idx) const
|
bool Selection::is_from_fully_selected_instance(unsigned int volume_idx) const
|
||||||
{
|
{
|
||||||
|
if (m_mode == Instance && wxGetApp().plater()->canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
struct SameInstance
|
struct SameInstance
|
||||||
{
|
{
|
||||||
int obj_idx;
|
int obj_idx;
|
||||||
|
@ -3180,14 +3154,14 @@ void Selection::paste_objects_from_clipboard()
|
||||||
Vec3d displacement;
|
Vec3d displacement;
|
||||||
bool in_current = plate->intersects(bbox);
|
bool in_current = plate->intersects(bbox);
|
||||||
auto start_point = in_current ? bbox.center() : plate->get_build_volume().center();
|
auto start_point = in_current ? bbox.center() : plate->get_build_volume().center();
|
||||||
|
auto start_offset = in_current ? src_object->instances.front()->get_offset() : plate->get_build_volume().center();
|
||||||
if (shift_all(0) != 0 || shift_all(1) != 0) {
|
if (shift_all(0) != 0 || shift_all(1) != 0) {
|
||||||
// BBS: if multiple objects are selected, move them as a whole after copy
|
// BBS: if multiple objects are selected, move them as a whole after copy
|
||||||
if (i == 0) empty_cell_all = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1,bbox.size()(1)+1});
|
if (i == 0) empty_cell_all = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1,bbox.size()(1)+1});
|
||||||
auto instance_shift = src_object->instances.front()->get_offset() - src_objects[0]->instances.front()->get_offset();
|
auto instance_shift = src_object->instances.front()->get_offset() - src_objects[0]->instances.front()->get_offset();
|
||||||
displacement = {shift_all.x() + empty_cell_all.x()+instance_shift.x(), shift_all.y() + empty_cell_all.y()+instance_shift.y(), start_point(2)};
|
displacement = {shift_all.x() + empty_cell_all.x() + instance_shift.x(), shift_all.y() + empty_cell_all.y() + instance_shift.y(), start_offset(2)};
|
||||||
} else {
|
} else {
|
||||||
// BBS: if only one object is copied, find an empty cell to put it
|
// BBS: if only one object is copied, find an empty cell to put it
|
||||||
auto start_offset = in_current ? src_object->instances.front()->get_offset() : plate->get_build_volume().center();
|
|
||||||
auto point_offset = start_offset - start_point;
|
auto point_offset = start_offset - start_point;
|
||||||
auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1, bbox.size()(1)+1});
|
auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1, bbox.size()(1)+1});
|
||||||
displacement = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_offset(2)};
|
displacement = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_offset(2)};
|
||||||
|
|
|
@ -15,6 +15,7 @@ class Model;
|
||||||
class ModelObject;
|
class ModelObject;
|
||||||
class ModelVolume;
|
class ModelVolume;
|
||||||
class ObjectID;
|
class ObjectID;
|
||||||
|
class ModelInstance;
|
||||||
class GLVolume;
|
class GLVolume;
|
||||||
class GLArrow;
|
class GLArrow;
|
||||||
class GLCurvedArrow;
|
class GLCurvedArrow;
|
||||||
|
@ -225,6 +226,9 @@ public:
|
||||||
void remove_volumes(EMode mode, const std::vector<unsigned int>& volume_idxs);
|
void remove_volumes(EMode mode, const std::vector<unsigned int>& volume_idxs);
|
||||||
|
|
||||||
//BBS
|
//BBS
|
||||||
|
ModelVolume * get_selected_single_volume(int &out_object_idx, int &out_volume_idx) const;
|
||||||
|
ModelObject * get_selected_single_object(int &out_object_idx) const;
|
||||||
|
const ModelInstance * get_selected_single_intance() const;
|
||||||
void add_curr_plate();
|
void add_curr_plate();
|
||||||
void add_object_from_idx(std::vector<int>& object_idxs);
|
void add_object_from_idx(std::vector<int>& object_idxs);
|
||||||
void remove_curr_plate();
|
void remove_curr_plate();
|
||||||
|
@ -326,20 +330,17 @@ public:
|
||||||
const std::pair<Vec3d, double> get_bounding_sphere() const;
|
const std::pair<Vec3d, double> get_bounding_sphere() const;
|
||||||
|
|
||||||
void setup_cache();
|
void setup_cache();
|
||||||
|
|
||||||
void translate(const Vec3d& displacement, TransformationType transformation_type);
|
void translate(const Vec3d& displacement, TransformationType transformation_type);
|
||||||
void move_to_center(const Vec3d& displacement, bool local = false);
|
void move_to_center(const Vec3d& displacement, bool local = false);
|
||||||
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
||||||
void flattening_rotate(const Vec3d& normal);
|
void flattening_rotate(const Vec3d& normal);
|
||||||
[[deprecated("Only used by GizmoObjectManipulation")]]
|
|
||||||
void scale_legacy(const Vec3d& scale, TransformationType transformation_type);
|
|
||||||
void scale(const Vec3d& scale, TransformationType transformation_type);
|
void scale(const Vec3d& scale, TransformationType transformation_type);
|
||||||
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||||
void scale_to_fit_print_volume(const BuildVolume& volume);
|
void scale_to_fit_print_volume(const BuildVolume& volume);
|
||||||
#else
|
#else
|
||||||
void scale_to_fit_print_volume(const DynamicPrintConfig& config);
|
void scale_to_fit_print_volume(const DynamicPrintConfig& config);
|
||||||
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
|
||||||
void scale_and_translate(const Vec3d& scale, const Vec3d& world_translation, TransformationType transformation_type);
|
void scale_and_translate(const Vec3d &scale, const Vec3d &world_translation, TransformationType transformation_type);
|
||||||
void mirror(Axis axis, TransformationType transformation_type);
|
void mirror(Axis axis, TransformationType transformation_type);
|
||||||
|
|
||||||
void translate(unsigned int object_idx, const Vec3d& displacement);
|
void translate(unsigned int object_idx, const Vec3d& displacement);
|
||||||
|
@ -351,6 +352,7 @@ public:
|
||||||
//BBS: add partplate related logic
|
//BBS: add partplate related logic
|
||||||
void notify_instance_update(int object_idx, int instance_idx);
|
void notify_instance_update(int object_idx, int instance_idx);
|
||||||
// BBS
|
// BBS
|
||||||
|
EMode get_volume_selection_mode(){ return m_volume_selection_mode;}
|
||||||
void set_volume_selection_mode(EMode mode) { if (!m_volume_selection_locked) m_volume_selection_mode = mode; }
|
void set_volume_selection_mode(EMode mode) { if (!m_volume_selection_locked) m_volume_selection_mode = mode; }
|
||||||
void lock_volume_selection_mode() { m_volume_selection_locked = true; }
|
void lock_volume_selection_mode() { m_volume_selection_locked = true; }
|
||||||
void unlock_volume_selection_mode() { m_volume_selection_locked = false; }
|
void unlock_volume_selection_mode() { m_volume_selection_locked = false; }
|
||||||
|
@ -358,11 +360,11 @@ public:
|
||||||
void erase();
|
void erase();
|
||||||
|
|
||||||
void render(float scale_factor = 1.0);
|
void render(float scale_factor = 1.0);
|
||||||
//BBS: GUI refactor: add uniform scale from gizmo
|
|
||||||
void render_sidebar_hints(const std::string& sidebar_field, bool uniform_scale);
|
|
||||||
#if ENABLE_RENDER_SELECTION_CENTER
|
#if ENABLE_RENDER_SELECTION_CENTER
|
||||||
void render_center(bool gizmo_is_dragging);
|
void render_center(bool gizmo_is_dragging);
|
||||||
#endif // ENABLE_RENDER_SELECTION_CENTER
|
#endif // ENABLE_RENDER_SELECTION_CENTER
|
||||||
|
//BBS: GUI refactor: add uniform scale from gizmo
|
||||||
|
void render_sidebar_hints(const std::string& sidebar_field, bool uniform_scale);
|
||||||
|
|
||||||
bool requires_local_axes() const;
|
bool requires_local_axes() const;
|
||||||
|
|
||||||
|
@ -405,7 +407,8 @@ private:
|
||||||
void set_bounding_boxes_dirty() {
|
void set_bounding_boxes_dirty() {
|
||||||
m_bounding_box.reset();
|
m_bounding_box.reset();
|
||||||
m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset();
|
m_unscaled_instance_bounding_box.reset(); m_scaled_instance_bounding_box.reset();
|
||||||
m_full_unscaled_instance_bounding_box.reset(); m_full_scaled_instance_bounding_box.reset();
|
m_full_unscaled_instance_bounding_box.reset();
|
||||||
|
m_full_scaled_instance_bounding_box.reset();
|
||||||
m_full_unscaled_instance_local_bounding_box.reset();
|
m_full_unscaled_instance_local_bounding_box.reset();
|
||||||
m_bounding_box_in_current_reference_system.reset();
|
m_bounding_box_in_current_reference_system.reset();
|
||||||
m_bounding_sphere.reset();
|
m_bounding_sphere.reset();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue