Merge branch 'dev_native' into vb_dev_native_background_processing

This commit is contained in:
bubnikv 2018-10-23 11:26:15 +02:00
commit edc79cb922
47 changed files with 1617 additions and 238 deletions

View file

@ -198,6 +198,9 @@ GLVolume::GLVolume(float r, float g, float b, float a)
: m_offset(Vec3d::Zero())
, m_rotation(Vec3d::Zero())
, m_scaling_factor(Vec3d::Ones())
#if ENABLE_MIRROR
, m_mirror(Vec3d::Ones())
#endif // ENABLE_MIRROR
, m_world_matrix(Transform3f::Identity())
, m_world_matrix_dirty(true)
, m_transformed_bounding_box_dirty(true)
@ -324,6 +327,40 @@ void GLVolume::set_scaling_factor(const Vec3d& scaling_factor)
}
}
#if ENABLE_MIRROR
const Vec3d& GLVolume::get_mirror() const
{
return m_mirror;
}
double GLVolume::get_mirror(Axis axis) const
{
return m_mirror(axis);
}
void GLVolume::set_mirror(const Vec3d& mirror)
{
if (m_mirror != mirror)
{
m_mirror = mirror;
m_world_matrix_dirty = true;
m_transformed_bounding_box_dirty = true;
m_transformed_convex_hull_bounding_box_dirty = true;
}
}
void GLVolume::set_mirror(Axis axis, double mirror)
{
if (m_mirror(axis) != mirror)
{
m_mirror(axis) = mirror;
m_world_matrix_dirty = true;
m_transformed_bounding_box_dirty = true;
m_transformed_convex_hull_bounding_box_dirty = true;
}
}
#endif // ENABLE_MIRROR
void GLVolume::set_convex_hull(const TriangleMesh& convex_hull)
{
m_convex_hull = &convex_hull;
@ -353,7 +390,11 @@ const Transform3f& GLVolume::world_matrix() const
{
if (m_world_matrix_dirty)
{
#if ENABLE_MIRROR
m_world_matrix = Geometry::assemble_transform(m_offset, m_rotation, m_scaling_factor, m_mirror).cast<float>();
#else
m_world_matrix = Geometry::assemble_transform(m_offset, m_rotation, m_scaling_factor).cast<float>();
#endif // ENABLE_MIRROR
m_world_matrix_dirty = false;
}
return m_world_matrix;
@ -729,6 +770,9 @@ std::vector<int> GLVolumeCollection::load_object(
v.set_offset(instance->get_offset());
v.set_rotation(instance->get_rotation());
v.set_scaling_factor(instance->get_scaling_factor());
#if ENABLE_MIRROR
v.set_mirror(instance->get_mirror());
#endif // ENABLE_MIRROR
}
}
@ -2076,6 +2120,15 @@ int _3DScene::get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol_idx)
return s_canvas_mgr.get_in_object_volume_id(canvas, scene_vol_idx);
}
#if ENABLE_MIRROR
#if ENABLE_EXTENDED_SELECTION
void _3DScene::mirror_selection(wxGLCanvas* canvas, Axis axis)
{
s_canvas_mgr.mirror_selection(canvas, axis);
}
#endif // ENABLE_EXTENDED_SELECTION
#endif // ENABLE_MIRROR
void _3DScene::reload_scene(wxGLCanvas* canvas, bool force)
{
s_canvas_mgr.reload_scene(canvas, force);

View file

@ -260,6 +260,10 @@ private:
Vec3d m_rotation;
// Scale factor along the three axes of the volume to be rendered.
Vec3d m_scaling_factor;
#if ENABLE_MIRROR
// Mirroring along the three axes of the volume to be rendered.
Vec3d m_mirror;
#endif // ENABLE_MIRROR
// World matrix of the volume to be rendered.
mutable Transform3f m_world_matrix;
// Whether or not is needed to recalculate the world matrix.
@ -337,6 +341,13 @@ public:
#endif // ENABLE_EXTENDED_SELECTION
void set_scaling_factor(const Vec3d& scaling_factor);
#if ENABLE_MIRROR
const Vec3d& get_mirror() const;
double get_mirror(Axis axis) const;
void set_mirror(const Vec3d& mirror);
void set_mirror(Axis axis, double mirror);
#endif // ENABLE_MIRROR
const Vec3d& get_offset() const;
void set_offset(const Vec3d& offset);
@ -581,6 +592,12 @@ public:
static int get_first_volume_id(wxGLCanvas* canvas, int obj_idx);
static int get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol_idx);
#if ENABLE_MIRROR
#if ENABLE_EXTENDED_SELECTION
static void mirror_selection(wxGLCanvas* canvas, Axis axis);
#endif // ENABLE_EXTENDED_SELECTION
#endif // ENABLE_MIRROR
static void reload_scene(wxGLCanvas* canvas, bool force);
static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);

View file

@ -54,10 +54,13 @@ public:
virtual bool
AcceptsFocusFromKeyboard() const { return false; }
void set_as_hidden() {
Hide();
hidden = true;
}
virtual bool Show(bool show = true) override {
if (!show)
hidden = true;
return wxButton::Show(!hidden);
return wxButton::Show(hidden ? false : show);
}
};

View file

@ -1409,14 +1409,13 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation)
if (!m_valid)
return;
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
for (unsigned int i : m_list)
{
if (is_single_full_instance())
(*m_volumes)[i]->set_rotation(rotation);
else
{
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
// extracts rotations from the composed transformation
Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_rotation_matrix());
@ -1436,15 +1435,13 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale)
if (!m_valid)
return;
Transform3d m = Transform3d::Identity();
m.scale(scale);
for (unsigned int i : m_list)
{
if (is_single_full_instance())
(*m_volumes)[i]->set_scaling_factor(scale);
else
{
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_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());
@ -1460,6 +1457,25 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale)
m_bounding_box_dirty = true;
}
#if ENABLE_MIRROR
void GLCanvas3D::Selection::mirror(Axis axis)
{
if (!m_valid)
return;
for (unsigned int i : m_list)
{
if (is_single_full_instance())
(*m_volumes)[i]->set_mirror(axis, -(*m_volumes)[i]->get_mirror(axis));
}
if (m_mode == Instance)
_synchronize_unselected_instances();
m_bounding_box_dirty = true;
}
#endif // ENABLE_MIRROR
void GLCanvas3D::Selection::render(bool show_indirect_selection) const
{
if (is_empty())
@ -1783,6 +1799,9 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances()
int instance_idx = volume->instance_idx();
const Vec3d& rotation = volume->get_rotation();
const Vec3d& scaling_factor = volume->get_scaling_factor();
#if ENABLE_MIRROR
const Vec3d& mirror = volume->get_mirror();
#endif // ENABLE_MIRROR
// Process unselected instances.
for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
@ -1799,6 +1818,9 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances()
v->set_rotation(rotation);
v->set_scaling_factor(scaling_factor);
#if ENABLE_MIRROR
v->set_mirror(mirror);
#endif // ENABLE_MIRROR
done.insert(j);
}
@ -2674,9 +2696,11 @@ wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent);
#if !ENABLE_EXTENDED_SELECTION
wxDEFINE_EVENT(EVT_GLCANVAS_ROTATE_OBJECT, Event<int>);
wxDEFINE_EVENT(EVT_GLCANVAS_SCALE_UNIFORMLY, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_OBJECTS, Event<int>);
#endif // !ENABLE_EXTENDED_SELECTION
wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_INSTANCES, Event<int>);
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
@ -3404,6 +3428,17 @@ int GLCanvas3D::get_in_object_volume_id(int scene_vol_idx) const
return ((0 <= scene_vol_idx) && (scene_vol_idx < (int)m_volumes.volumes.size())) ? m_volumes.volumes[scene_vol_idx]->volume_idx() : -1;
}
#if ENABLE_MIRROR
#if ENABLE_EXTENDED_SELECTION
void GLCanvas3D::mirror_selection(Axis axis)
{
m_selection.mirror(axis);
_on_mirror();
wxGetApp().obj_manipul()->update_settings_value(m_selection);
}
#endif // ENABLE_EXTENDED_SELECTION
#endif // ENABLE_MIRROR
void GLCanvas3D::reload_scene(bool force)
{
if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr))
@ -3421,7 +3456,12 @@ void GLCanvas3D::reload_scene(bool force)
#if ENABLE_EXTENDED_SELECTION
if (m_regenerate_volumes)
{
reset_volumes();
// to update the toolbar
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
}
#endif // ENABLE_EXTENDED_SELECTION
set_bed_shape(dynamic_cast<const ConfigOptionPoints*>(m_config->option("bed_shape"))->values);
@ -3441,9 +3481,6 @@ void GLCanvas3D::reload_scene(bool force)
{
load_object(*m_model, obj_idx);
}
// to update the toolbar
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
}
update_gizmos_data();
@ -3685,24 +3722,26 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
switch (keyCode)
{
// key +
case 43: { post_event(Event<int>(EVT_GLCANVAS_INCREASE_OBJECTS, +1)); break; }
case 43: { post_event(Event<int>(EVT_GLCANVAS_INCREASE_INSTANCES, +1)); break; }
// key -
case 45: { post_event(Event<int>(EVT_GLCANVAS_INCREASE_OBJECTS, -1)); break; }
case 45: { post_event(Event<int>(EVT_GLCANVAS_INCREASE_INSTANCES, -1)); break; }
// key A/a
case 65:
case 97: { post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE)); break; }
// key B/b
case 66:
case 98: { zoom_to_bed(); break; }
#if !ENABLE_EXTENDED_SELECTION
// key L/l
case 76:
case 108: { post_event(Event<int>(EVT_GLCANVAS_ROTATE_OBJECT, -1)); break; }
// key R/r
// key R/r
case 82:
case 114: { post_event(Event<int>(EVT_GLCANVAS_ROTATE_OBJECT, +1)); break; }
// key S/s
// key S/s
case 83:
case 115: { post_event(SimpleEvent(EVT_GLCANVAS_SCALE_UNIFORMLY)); break; }
#endif // !ENABLE_EXTENDED_SELECTION
// key Z/z
case 90:
case 122: { zoom_to_volumes(); break; }
@ -3820,7 +3859,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
case Gizmos::Scale:
{
#if ENABLE_EXTENDED_SELECTION
m_regenerate_volumes = false;
m_selection.scale(m_gizmos.get_scale());
_on_scale();
#else
@ -3837,7 +3875,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
case Gizmos::Rotate:
{
#if ENABLE_EXTENDED_SELECTION
m_regenerate_volumes = false;
m_selection.rotate(m_gizmos.get_rotation());
_on_rotate();
#else
@ -3903,9 +3940,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
#endif // ENABLE_EXTENDED_SELECTION
#if ENABLE_EXTENDED_SELECTION
else if (!m_selection.is_empty() && m_gizmos.grabber_contains_mouse())
else if (evt.LeftDown() && !m_selection.is_empty() && m_gizmos.grabber_contains_mouse())
#else
else if ((selected_object_idx != -1) && m_gizmos.grabber_contains_mouse())
else if (evt.LeftDown() && (selected_object_idx != -1) && m_gizmos.grabber_contains_mouse())
#endif // ENABLE_EXTENDED_SELECTION
{
update_gizmos_data();
@ -3920,7 +3957,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (m_gizmos.get_current_type() == Gizmos::Flatten) {
// Rotate the object so the normal points downward:
#if ENABLE_EXTENDED_SELECTION
m_regenerate_volumes = false;
m_selection.rotate(m_gizmos.get_flattening_rotation());
_on_flatten();
wxGetApp().obj_manipul()->update_settings_value(m_selection);
@ -3951,14 +3987,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
#if ENABLE_EXTENDED_SELECTION
if (evt.LeftDown() && (m_hover_volume_id != -1))
{
if (evt.ControlDown())
m_selection.remove(m_hover_volume_id);
else
if (!evt.ShiftDown() || !m_selection.contains_volume(m_hover_volume_id))
m_selection.add(m_hover_volume_id, !evt.ShiftDown());
else
m_selection.remove(m_hover_volume_id);
m_gizmos.update_on_off_state(m_selection);
update_gizmos_data();
wxGetApp().obj_manipul()->update_settings_value(m_selection);
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
m_dirty = true;
}
#else
@ -3983,16 +4020,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
// propagate event through callback
#if ENABLE_EXTENDED_SELECTION
if (m_picking_enabled && (m_hover_volume_id != -1))
{
int object_idx = m_selection.get_object_idx();
_on_select(m_hover_volume_id, object_idx);
}
#else
#if !ENABLE_EXTENDED_SELECTION
if (m_picking_enabled && (volume_idx != -1))
_on_select(volume_idx, selected_object_idx);
#endif // ENABLE_EXTENDED_SELECTION
#endif // !ENABLE_EXTENDED_SELECTION
#if ENABLE_EXTENDED_SELECTION
if (m_hover_volume_id != -1)
@ -4319,10 +4350,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
#if ENABLE_EXTENDED_SELECTION
m_selection.clear();
wxGetApp().obj_manipul()->update_settings_value(m_selection);
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
#else
deselect_volumes();
#endif // ENABLE_EXTENDED_SELECTION
_on_select(-1, -1);
#endif // ENABLE_EXTENDED_SELECTION
update_gizmos_data();
}
#if ENABLE_GIZMOS_RESET
@ -4363,7 +4395,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
case Gizmos::Scale:
{
#if ENABLE_EXTENDED_SELECTION
m_regenerate_volumes = false;
_on_scale();
#endif // ENABLE_EXTENDED_SELECTION
break;
@ -4371,7 +4402,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
case Gizmos::Rotate:
{
#if ENABLE_EXTENDED_SELECTION
m_regenerate_volumes = false;
_on_rotate();
#else
post_event(Vec3dEvent(EVT_GIZMO_ROTATE, m_gizmos.get_rotation()));
@ -6524,6 +6554,41 @@ void GLCanvas3D::_on_flatten()
_on_rotate();
}
#if ENABLE_MIRROR
void GLCanvas3D::_on_mirror()
{
if (m_model == nullptr)
return;
std::set<std::pair<int, int>> done; // prevent mirroring instances twice
for (const GLVolume* v : m_volumes.volumes)
{
int object_idx = v->object_idx();
if (object_idx >= 1000)
continue;
int instance_idx = v->instance_idx();
// prevent mirroring instances twice
std::pair<int, int> done_id(object_idx, instance_idx);
if (done.find(done_id) != done.end())
continue;
done.insert(done_id);
// Mirror instances.
ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr)
{
model_object->instances[instance_idx]->set_mirror(v->get_mirror());
model_object->invalidate_bounding_box();
}
}
// schedule_background_process
}
#endif // ENABLE_MIRROR
#else
void GLCanvas3D::_on_move(const std::vector<int>& volume_idxs)
{
@ -6572,11 +6637,9 @@ void GLCanvas3D::_on_move(const std::vector<int>& volume_idxs)
}
#endif // ENABLE_EXTENDED_SELECTION
#if !ENABLE_EXTENDED_SELECTION
void GLCanvas3D::_on_select(int volume_idx, int object_idx)
{
#if ENABLE_EXTENDED_SELECTION
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
#else
int vol_id = -1;
int obj_id = -1;
@ -6605,8 +6668,8 @@ void GLCanvas3D::_on_select(int volume_idx, int object_idx)
post_event(ObjectSelectEvent(obj_id, vol_id));
wxGetApp().obj_list()->select_current_volume(obj_id, vol_id);
#endif // !ENABLE_EXTENDED_SELECTION
}
#endif // !ENABLE_EXTENDED_SELECTION
std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& colors)
{

View file

@ -112,9 +112,11 @@ wxDECLARE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent);
#if !ENABLE_EXTENDED_SELECTION
wxDECLARE_EVENT(EVT_GLCANVAS_ROTATE_OBJECT, Event<int>); // data: -1 => rotate left, +1 => rotate right
wxDECLARE_EVENT(EVT_GLCANVAS_SCALE_UNIFORMLY, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_INCREASE_OBJECTS, Event<int>); // data: +1 => increase, -1 => decrease
#endif // !ENABLE_EXTENDED_SELECTION
wxDECLARE_EVENT(EVT_GLCANVAS_INCREASE_INSTANCES, Event<int>); // data: +1 => increase, -1 => decrease
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
@ -483,6 +485,8 @@ public:
bool is_from_single_instance() const { return get_instance_idx() != -1; }
bool is_from_single_object() const { return get_object_idx() != -1; }
bool contains_volume(unsigned int volume_idx) const { return std::find(m_list.begin(), m_list.end(), volume_idx) != m_list.end(); }
// Returns the the object id if the selection is from a single object, otherwise is -1
int get_object_idx() const;
// Returns the instance id if the selection is from a single object and from a single instance, otherwise is -1
@ -499,6 +503,9 @@ public:
void translate(const Vec3d& displacement);
void rotate(const Vec3d& rotation);
void scale(const Vec3d& scale);
#if ENABLE_MIRROR
void mirror(Axis axis);
#endif // ENABLE_MIRROR
void render(bool show_indirect_selection) const;
@ -831,6 +838,12 @@ public:
int get_first_volume_id(int obj_idx) const;
int get_in_object_volume_id(int scene_vol_idx) const;
#if ENABLE_MIRROR
#if ENABLE_EXTENDED_SELECTION
void mirror_selection(Axis axis);
#endif // ENABLE_EXTENDED_SELECTION
#endif // ENABLE_MIRROR
void reload_scene(bool force);
void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
@ -953,10 +966,15 @@ private:
void _on_rotate();
void _on_scale();
void _on_flatten();
#if ENABLE_MIRROR
void _on_mirror();
#endif // ENABLE_MIRROR
#else
void _on_move(const std::vector<int>& volume_idxs);
#endif // ENABLE_EXTENDED_SELECTION
#if !ENABLE_EXTENDED_SELECTION
void _on_select(int volume_idx, int object_idx);
#endif // !ENABLE_EXTENDED_SELECTION
// generates the legend texture in dependence of the current shown view type
void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);

View file

@ -596,6 +596,17 @@ int GLCanvas3DManager::get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol
return (it != m_canvases.end()) ? it->second->get_in_object_volume_id(scene_vol_idx) : -1;
}
#if ENABLE_MIRROR
#if ENABLE_EXTENDED_SELECTION
void GLCanvas3DManager::mirror_selection(wxGLCanvas* canvas, Axis axis)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->mirror_selection(axis);
}
#endif // ENABLE_EXTENDED_SELECTION
#endif // ENABLE_MIRROR
void GLCanvas3DManager::reload_scene(wxGLCanvas* canvas, bool force)
{
CanvasesMap::iterator it = _get_canvas(canvas);

View file

@ -163,6 +163,12 @@ public:
int get_first_volume_id(wxGLCanvas* canvas, int obj_idx) const;
int get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol_idx) const;
#if ENABLE_MIRROR
#if ENABLE_EXTENDED_SELECTION
void mirror_selection(wxGLCanvas* canvas, Axis axis);
#endif // ENABLE_EXTENDED_SELECTION
#endif // ENABLE_MIRROR
void reload_scene(wxGLCanvas* canvas, bool force);
void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);

View file

@ -868,7 +868,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
BoundingBoxf3 box;
Transform3d transform = Transform3d::Identity();
Vec3d angles = Vec3d::Zero();
Transform3d rotation = Transform3d::Identity();
Transform3d offsets_transform = Transform3d::Identity();
if (selection.is_from_single_instance())
{
@ -880,13 +880,19 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
}
// gets transform from first selected volume
transform = selection.get_volume(*idxs.begin())->world_matrix().cast<double>();
const GLVolume* v = selection.get_volume(*idxs.begin());
transform = v->world_matrix().cast<double>();
// extract angles from transform
angles = Slic3r::Geometry::extract_euler_angles(transform);
// gets angles from first selected volume
angles = v->get_rotation();
#if ENABLE_MIRROR
// consider rotation+mirror only components of the transform for offsets
offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_mirror());
#else
// set rotation-only component of transform
rotation = Geometry::assemble_transform(Vec3d::Zero(), angles);
offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles);
#endif // ENABLE_MIRROR
}
else
box = selection.get_bounding_box();
@ -898,9 +904,9 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
const Vec3d& center = m_box.center();
#if ENABLE_EXTENDED_SELECTION
Vec3d offset_x = rotation * Vec3d((double)Offset, 0.0, 0.0);
Vec3d offset_y = rotation * Vec3d(0.0, (double)Offset, 0.0);
Vec3d offset_z = rotation * Vec3d(0.0, 0.0, (double)Offset);
Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0);
Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0);
Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset);
#endif // ENABLE_EXTENDED_SELECTION
// x axis
@ -1468,6 +1474,7 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const
::glEnable(GL_BLEND);
::glEnable(GL_DEPTH_TEST);
::glDisable(GL_CULL_FACE);
for (int i=0; i<(int)m_planes.size(); ++i) {
if (i == m_hover_id)
@ -1506,6 +1513,7 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const
#endif // ENABLE_EXTENDED_SELECTION
}
::glEnable(GL_CULL_FACE);
::glDisable(GL_BLEND);
}
@ -1516,6 +1524,7 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const
#endif // ENABLE_EXTENDED_SELECTION
{
::glEnable(GL_DEPTH_TEST);
::glDisable(GL_CULL_FACE);
for (unsigned int i = 0; i < m_planes.size(); ++i)
{
@ -1546,6 +1555,8 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const
}
#endif // ENABLE_EXTENDED_SELECTION
}
::glEnable(GL_CULL_FACE);
}
void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
@ -1769,9 +1780,9 @@ Vec3d GLGizmoFlatten::get_flattening_rotation() const
// calculates the rotations in model space, taking in account the scaling factors
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> m = m_model_object->instances.front()->world_matrix(true, true).matrix().block(0, 0, 3, 3).inverse().transpose();
Eigen::Quaterniond q;
Vec3d angles = q.setFromTwoVectors(m * m_normal, -Vec3d::UnitZ()).toRotationMatrix().eulerAngles(2, 1, 0);
Vec3d angles = Geometry::extract_euler_angles(q.setFromTwoVectors(m * m_normal, -Vec3d::UnitZ()).toRotationMatrix());
m_normal = Vec3d::Zero();
return Vec3d(angles(2), angles(1), angles(0));
return angles;
}
} // namespace GUI

View file

@ -327,24 +327,6 @@ void GUI_App::CallAfter(std::function<void()> cb)
callback_register.unlock();
}
wxMenuItem* GUI_App::append_submenu(wxMenu* menu,
wxMenu* sub_menu,
int id,
const wxString& string,
const wxString& description,
const std::string& icon)
{
if (id == wxID_ANY)
id = wxNewId();
auto item = new wxMenuItem(menu, id, string, description);
if (!icon.empty())
item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG));
item->SetSubMenu(sub_menu);
menu->Append(item);
return item;
}
void GUI_App::window_pos_save(wxTopLevelWindow* window, const std::string &name)
{
if (name.empty()) { return; }
@ -500,7 +482,8 @@ ConfigMenuIDs GUI_App::get_view_mode()
return ConfigMenuModeSimple;
const auto mode = app_config->get("view_mode");
return mode == "expert" ? ConfigMenuModeExpert : ConfigMenuModeSimple;
return mode == "expert" ? ConfigMenuModeExpert :
mode == "simple" ? ConfigMenuModeSimple : ConfigMenuModeMiddle;
}
// Update view mode according to selected menu
@ -518,6 +501,11 @@ void GUI_App::update_mode()
sidebar().Layout();
mainframe->m_plater->Layout();
ConfigOptionMode opt_mode = mode == ConfigMenuModeSimple ? comSimple :
mode == ConfigMenuModeExpert ? comExpert : comMiddle;
for (auto tab : tabs_list)
tab->update_visibility(opt_mode);
}
void GUI_App::add_config_menu(wxMenuBar *menu)
@ -537,6 +525,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
local_menu->AppendSeparator();
auto mode_menu = new wxMenu();
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _(L("&Simple")), _(L("Simple View Mode")));
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeMiddle, _(L("&Middle")), _(L("Middle View Mode")));
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeExpert, _(L("&Expert")), _(L("Expert View Mode")));
mode_menu->Check(config_id_base + get_view_mode(), true);
local_menu->AppendSubMenu(mode_menu, _(L("&Mode")), _(L("Slic3r View Mode")));
@ -607,8 +596,9 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
}
});
mode_menu->Bind(wxEVT_MENU, [this, config_id_base](wxEvent& event) {
std::string mode = event.GetId() - config_id_base == ConfigMenuModeExpert ?
"expert" : "simple";
int id_mode = event.GetId() - config_id_base;
std::string mode = id_mode == ConfigMenuModeExpert ? "expert" :
id_mode == ConfigMenuModeSimple ? "simple" : "middle";
app_config->set("view_mode", mode);
app_config->save();
update_mode();

View file

@ -51,6 +51,7 @@ enum ConfigMenuIDs {
ConfigMenuUpdate,
ConfigMenuPreferences,
ConfigMenuModeSimple,
ConfigMenuModeMiddle,
ConfigMenuModeExpert,
ConfigMenuLanguage,
ConfigMenuFlashFirmware,
@ -107,12 +108,6 @@ public:
// void notify(/*message*/);
void update_ui_from_settings();
void CallAfter(std::function<void()> cb);
wxMenuItem* append_submenu(wxMenu* menu,
wxMenu* sub_menu,
int id,
const wxString& string,
const wxString& description,
const std::string& icon);
void window_pos_save(wxTopLevelWindow* window, const std::string &name);
void window_pos_restore(wxTopLevelWindow* window, const std::string &name);

View file

@ -868,7 +868,7 @@ void ObjectList::del_settings_from_config()
void ObjectList::del_instances_from_object(const int obj_idx)
{
auto instances = (*m_objects)[obj_idx]->instances;
auto& instances = (*m_objects)[obj_idx]->instances;
if (instances.size() <= 1)
return;
@ -1054,7 +1054,11 @@ void ObjectList::part_selection_changed()
m_selected_object_id = obj_idx;
#if ENABLE_EXTENDED_SELECTION
wxGetApp().obj_manipul()->update_settings_value(_3DScene::get_canvas(wxGetApp().canvas3D())->get_selection());
#else
wxGetApp().obj_manipul()->update_values();
#endif // ENABLE_EXTENDED_SELECTION
}
void ObjectList::update_manipulation_sizer(const bool is_simple_mode)

View file

@ -4,6 +4,7 @@
#include <wx/bitmap.h>
#include <wx/dataview.h>
#include <map>
#include <vector>
class wxBoxSizer;
class PrusaObjectDataViewModel;

View file

@ -221,7 +221,7 @@ void ObjectManipulation::update_settings_list()
if (cat.second.size() == 1 && cat.second[0] == "extruder")
continue;
auto optgroup = std::make_shared<ConfigOptionsGroup>(parent, cat.first, config, false, ogDEFAULT, extra_column);
auto optgroup = std::make_shared<ConfigOptionsGroup>(parent, cat.first, config, false, extra_column);
optgroup->label_width = 150;
optgroup->sidetext_width = 70;

View file

@ -6,7 +6,6 @@
#include <wx/toplevel.h>
#include <wx/sizer.h>
#include <wx/panel.h>
#include <wx/checkbox.h>
#include "libslic3r/Config.hpp"
@ -16,6 +15,30 @@ namespace Slic3r {
namespace GUI {
CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent)
: wxPanel(parent, wxID_ANY)
{
// WARN: wxMSW does some extra shenanigans to calc the extra control size.
// It first calls the create function with a dummy empty wxDialog parent and saves its size.
// Afterwards, the create function is called again with the real parent.
// Additionally there's no way to pass any extra data to the create function (no closure),
// which is why we have to this stuff here. Grrr!
auto *dlg = dynamic_cast<CheckboxFileDialog*>(parent);
const wxString checkbox_label(dlg != nullptr ? dlg->checkbox_label : wxString("String long enough to contain dlg->checkbox_label"));
auto* sizer = new wxBoxSizer(wxHORIZONTAL);
cbox = new wxCheckBox(this, wxID_ANY, checkbox_label);
cbox->SetValue(true);
sizer->AddSpacer(5);
sizer->Add(this->cbox, 0, wxEXPAND | wxALL, 5);
SetSizer(sizer);
sizer->SetSizeHints(this);
}
wxWindow* CheckboxFileDialog::ExtraPanel::ctor(wxWindow *parent) {
return new ExtraPanel(parent);
}
CheckboxFileDialog::CheckboxFileDialog(wxWindow *parent,
const wxString &checkbox_label,
bool checkbox_value,
@ -29,35 +52,22 @@ CheckboxFileDialog::CheckboxFileDialog(wxWindow *parent,
const wxString &name
)
: wxFileDialog(parent, message, default_dir, default_file, wildcard, style, pos, size, name)
, cbox(nullptr)
, checkbox_label(checkbox_label)
{
if (checkbox_label.IsEmpty()) {
return;
}
extra_control_creator = [this, checkbox_label](wxWindow *parent) -> wxWindow* {
wxPanel* panel = new wxPanel(parent, -1);
wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
this->cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, checkbox_label);
this->cbox->SetValue(true);
sizer->AddSpacer(5);
sizer->Add(this->cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
panel->SetSizer(sizer);
sizer->SetSizeHints(panel);
return panel;
};
SetExtraControlCreator(*extra_control_creator.target<ExtraControlCreatorFunction>());
SetExtraControlCreator(ExtraPanel::ctor);
}
bool CheckboxFileDialog::get_checkbox_value() const
{
return this->cbox != nullptr ? cbox->IsChecked() : false;
auto *extra_panel = dynamic_cast<ExtraPanel*>(GetExtraControl());
return extra_panel != nullptr ? extra_panel->cbox->GetValue() : false;
}
WindowMetrics WindowMetrics::from_window(wxTopLevelWindow *window)
{
WindowMetrics res;

View file

@ -8,6 +8,7 @@
#include <wx/filedlg.h>
#include <wx/gdicmn.h>
#include <wx/panel.h>
class wxCheckBox;
class wxTopLevelWindow;
@ -37,8 +38,15 @@ public:
bool get_checkbox_value() const;
private:
std::function<wxWindow*(wxWindow*)> extra_control_creator;
wxCheckBox *cbox;
struct ExtraPanel : public wxPanel
{
wxCheckBox *cbox;
ExtraPanel(wxWindow *parent);
static wxWindow* ctor(wxWindow *parent);
};
wxString checkbox_label;
};

View file

@ -296,13 +296,13 @@ void MainFrame::init_menubar()
if (m_plater) {
m_plater_menu = new wxMenu();
append_menu_item(m_plater_menu, wxID_ANY, _(L("Export G-code...")), _(L("Export current plate as G-code")),
[this](wxCommandEvent&){ /*m_plater->export_gcode(); */}, "cog_go.png");
[this](wxCommandEvent&){ m_plater->export_gcode(); }, "cog_go.png");
append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as STL...")), _(L("Export current plate as STL")),
[this](wxCommandEvent&){ /*m_plater->export_stl(); */}, "brick_go.png");
[this](wxCommandEvent&){ m_plater->export_stl(); }, "brick_go.png");
append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as AMF...")), _(L("Export current plate as AMF")),
[this](wxCommandEvent&){ /*m_plater->export_amf();*/ }, "brick_go.png");
[this](wxCommandEvent&){ m_plater->export_amf(); }, "brick_go.png");
append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as 3MF...")), _(L("Export current plate as 3MF")),
[this](wxCommandEvent&){ /*m_plater->export_3mf(); */}, "brick_go.png");
[this](wxCommandEvent&){ m_plater->export_3mf(); }, "brick_go.png");
}
// Window menu

View file

@ -97,8 +97,8 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
void OptionsGroup::add_undo_buttuns_to_sizer(wxSizer* sizer, const t_field& field)
{
if (!m_show_modified_btns) {
field->m_Undo_btn->Hide();
field->m_Undo_to_sys_btn->Hide();
field->m_Undo_btn->set_as_hidden();
field->m_Undo_to_sys_btn->set_as_hidden();
return;
}
@ -123,6 +123,10 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
for (auto opt : option_set)
m_options.emplace(opt.opt_id, opt);
// add mode value for current line to m_options_mode
if (!option_set.empty())
m_options_mode.push_back(option_set[0].opt.mode);
// if we have a single option with no label, no sidetext just add it directly to sizer
if (option_set.size() == 1 && label_width == 0 && option_set.front().opt.full_width &&
option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr &&
@ -156,16 +160,8 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
#endif /* __WXGTK__ */
// if we have an extra column, build it
if (extra_column) {
if (extra_column) {
grid_sizer->Add(extra_column(parent(), line), 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3);
}
else {
// if the callback provides no sizer for the extra cell, put a spacer
grid_sizer->AddSpacer(1);
}
}
if (extra_column)
grid_sizer->Add(extra_column(parent(), line), 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3);
// Build a label if we have it
wxStaticText* label=nullptr;
@ -182,16 +178,14 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
label->SetFont(label_font);
label->Wrap(label_width); // avoid a Linux/GTK bug
if (!line.near_label_widget)
grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) |
(m_flag == ogSIDE_OPTIONS_VERTICAL ? wxTOP : wxALIGN_CENTER_VERTICAL), 5);
grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5);
else {
// If we're here, we have some widget near the label
// so we need a horizontal sizer to arrange these things
auto sizer = new wxBoxSizer(wxHORIZONTAL);
grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1);
sizer->Add(line.near_label_widget(parent()), 0, wxRIGHT, 7);
sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) |
(m_flag == ogSIDE_OPTIONS_VERTICAL ? wxTOP : wxALIGN_CENTER_VERTICAL), 5);
sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5);
}
if (line.label_tooltip.compare("") != 0)
label->SetToolTip(line.label_tooltip);
@ -208,7 +202,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
// If we're here, we have more than one option or a single option with sidetext
// so we need a horizontal sizer to arrange these things
auto sizer = new wxBoxSizer(m_flag == ogSIDE_OPTIONS_VERTICAL ? wxVERTICAL : wxHORIZONTAL);
auto sizer = new wxBoxSizer(wxHORIZONTAL);
grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1);
// If we have a single option with no sidetext just add it directly to the grid sizer
if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 &&
@ -227,14 +221,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
for (auto opt : option_set) {
ConfigOptionDef option = opt.opt;
wxSizer* sizer_tmp;
if (m_flag == ogSIDE_OPTIONS_VERTICAL){
auto sz = new wxFlexGridSizer(1, 3, 2, 2);
sz->RemoveGrowableCol(2);
sizer_tmp = sz;
}
else
sizer_tmp = sizer;
wxSizer* sizer_tmp = sizer;
// add label if any
if (option.label != "") {
wxString str_label = _(option.label);
@ -260,7 +247,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
auto sidetext = new wxStaticText( parent(), wxID_ANY, _(option.sidetext), wxDefaultPosition,
wxSize(sidetext_width, -1)/*wxDefaultSize*/, wxALIGN_LEFT);
sidetext->SetFont(sidetext_font);
sizer_tmp->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, m_flag == ogSIDE_OPTIONS_VERTICAL ? 0 : 4);
sizer_tmp->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4);
field->set_side_text_ptr(sidetext);
}
@ -269,13 +256,10 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
sizer_tmp->Add(opt.side_widget(parent())/*!.target<wxWindow>()*/, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 1); //! requires verification
}
if (opt.opt_id != option_set.back().opt_id && m_flag != ogSIDE_OPTIONS_VERTICAL) //! istead of (opt != option_set.back())
if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back())
{
sizer_tmp->AddSpacer(6);
}
if (m_flag == ogSIDE_OPTIONS_VERTICAL)
sizer->Add(sizer_tmp, 0, wxALIGN_RIGHT|wxALL, 0);
}
// add extra sizers if any
for (auto extra_widget : line.get_extra_widgets()) {
@ -403,6 +387,39 @@ void ConfigOptionsGroup::reload_config(){
}
bool ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) {
if (m_options_mode.empty())
return true;
if (m_grid_sizer->GetEffectiveRowsCount() != m_options_mode.size() &&
m_options_mode.size() == 1)
return m_options_mode[0] <= mode;
sizer->ShowItems(true);
#ifdef __WXGTK__
m_panel->Show(true);
m_grid_sizer->Show(true);
#endif /* __WXGTK__ */
int coef = 0;
int hidden_row_cnt = 0;
const int cols = m_grid_sizer->GetCols();
for (auto opt_mode : m_options_mode) {
const bool show = opt_mode <= mode;
if (!show) {
hidden_row_cnt++;
for (int i = 0; i < cols; ++i)
m_grid_sizer->Show(coef + i, show);
}
coef+= cols;
}
if (hidden_row_cnt == m_options_mode.size()) {
sizer->ShowItems(false);
return false;
}
return true;
}
boost::any ConfigOptionsGroup::config_value(const std::string& opt_key, int opt_index, bool deserialize){
if (deserialize) {

View file

@ -27,11 +27,6 @@
namespace Slic3r { namespace GUI {
enum ogDrawFlag{
ogDEFAULT,
ogSIDE_OPTIONS_VERTICAL
};
/// Widget type describes a function object that returns a wxWindow (our widget) and accepts a wxWidget (parent window).
using widget_t = std::function<wxSizer*(wxWindow*)>;//!std::function<wxWindow*(wxWindow*)>;
@ -151,7 +146,6 @@ public:
inline void enable() { for (auto& field : m_fields) field.second->enable(); }
inline void disable() { for (auto& field : m_fields) field.second->disable(); }
void set_flag(ogDrawFlag flag) { m_flag = flag; }
void set_grid_vgap(int gap) { m_grid_sizer->SetVGap(gap); }
void set_show_modified_btns_val(bool show) {
@ -159,9 +153,10 @@ public:
}
OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false,
ogDrawFlag flag = ogDEFAULT, column_t extra_clmn = nullptr) :
m_parent(_parent), title(title), m_show_modified_btns(is_tab_opt),
staticbox(title!=""), m_flag(flag), extra_column(extra_clmn){
column_t extra_clmn = nullptr) :
m_parent(_parent), title(title),
m_show_modified_btns(is_tab_opt),
staticbox(title!=""), extra_column(extra_clmn){
if (staticbox) {
stb = new wxStaticBox(_parent, wxID_ANY, title);
stb->SetFont(wxGetApp().bold_font());
@ -172,7 +167,7 @@ public:
if (extra_column != nullptr) num_columns++;
m_grid_sizer = new wxFlexGridSizer(0, num_columns, 1,0);
static_cast<wxFlexGridSizer*>(m_grid_sizer)->SetFlexibleDirection(wxBOTH/*wxHORIZONTAL*/);
static_cast<wxFlexGridSizer*>(m_grid_sizer)->AddGrowableCol(label_width != 0);
static_cast<wxFlexGridSizer*>(m_grid_sizer)->AddGrowableCol(label_width == 0 ? 0 : !extra_column ? 1 : 2 );
#ifdef __WXGTK__
m_panel = new wxPanel( _parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
sizer->Fit(m_panel);
@ -187,6 +182,7 @@ public:
protected:
std::map<t_config_option_key, Option> m_options;
wxWindow* m_parent {nullptr};
std::vector<ConfigOptionMode> m_options_mode;
/// Field list, contains unique_ptrs of the derived type.
/// using types that need to know what it is beyond the public interface
@ -197,8 +193,6 @@ protected:
// "true" if option is created in preset tabs
bool m_show_modified_btns{ false };
ogDrawFlag m_flag{ ogDEFAULT };
// This panel is needed for correct showing of the ToolTips for Button, StaticText and CheckBox
// Tooltips on GTK doesn't work inside wxStaticBoxSizer unless you insert a panel
// inside it before you insert the other controls.
@ -223,8 +217,8 @@ protected:
class ConfigOptionsGroup: public OptionsGroup {
public:
ConfigOptionsGroup( wxWindow* parent, const wxString& title, DynamicPrintConfig* _config = nullptr,
bool is_tab_opt = false, ogDrawFlag flag = ogDEFAULT, column_t extra_clmn = nullptr) :
OptionsGroup(parent, title, is_tab_opt, flag, extra_clmn), m_config(_config) {}
bool is_tab_opt = false, column_t extra_clmn = nullptr) :
OptionsGroup(parent, title, is_tab_opt, extra_clmn), m_config(_config) {}
/// reference to libslic3r config, non-owning pointer (?).
DynamicPrintConfig* m_config {nullptr};
@ -252,6 +246,8 @@ public:
void back_to_config_value(const DynamicPrintConfig& config, const std::string& opt_key);
void on_kill_focus() override{ reload_config();}
void reload_config();
// return value shows visibility : false => all options are hidden
bool update_visibility(ConfigOptionMode mode);
boost::any config_value(const std::string& opt_key, int opt_index, bool deserialize);
// return option value from config
boost::any get_config_value(const DynamicPrintConfig& config, const std::string& opt_key, int opt_index = -1);

View file

@ -701,7 +701,7 @@ private:
static const std::regex pattern_drop;
};
const std::regex PlaterDropTarget::pattern_drop("[.](stl|obj|amf|3mf|prusa)$", std::regex::icase);
const std::regex PlaterDropTarget::pattern_drop(".*[.](stl|obj|amf|3mf|prusa)", std::regex::icase);
bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames)
{
@ -783,13 +783,19 @@ struct Plater::priv
#endif // ENABLE_EXTENDED_SELECTION
void selection_changed();
void object_list_changed();
#if !ENABLE_EXTENDED_SELECTION
void select_view();
#endif // !ENABLE_EXTENDED_SELECTION
void remove(size_t obj_idx);
void reset();
#if !ENABLE_EXTENDED_SELECTION
void rotate();
void mirror(const Axis &axis);
#endif // !ENABLE_EXTENDED_SELECTION
void mirror(Axis axis);
#if !ENABLE_EXTENDED_SELECTION
void scale();
#endif // !ENABLE_EXTENDED_SELECTION
void arrange();
void split_object();
void schedule_background_process();
@ -844,12 +850,17 @@ private:
bool can_split_object() const;
bool can_cut_object() const;
bool layers_height_allowed() const;
bool can_delete_all() const;
bool can_arrange() const;
#if ENABLE_MIRROR
bool can_mirror() const;
#endif // ENABLE_MIRROR
#endif // ENABLE_EXTENDED_SELECTION
};
const std::regex Plater::priv::pattern_bundle("[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)$", std::regex::icase);
const std::regex Plater::priv::pattern_3mf("[.]3mf$", std::regex::icase);
const std::regex Plater::priv::pattern_zip_amf("[.]zip[.]amf$", std::regex::icase);
const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)", std::regex::icase);
const std::regex Plater::priv::pattern_3mf(".*3mf", std::regex::icase);
const std::regex Plater::priv::pattern_zip_amf(".*[.]zip[.]amf", std::regex::icase);
Plater::priv::priv(Plater *q, MainFrame *main_frame) :
q(q),
@ -925,9 +936,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) :
canvas3D->Bind(EVT_GLCANVAS_MODEL_UPDATE, &priv::on_model_update, this);
canvas3D->Bind(EVT_GLCANVAS_REMOVE_OBJECT, [q](SimpleEvent&) { q->remove_selected(); });
canvas3D->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent&) { arrange(); });
#if !ENABLE_EXTENDED_SELECTION
canvas3D->Bind(EVT_GLCANVAS_ROTATE_OBJECT, [this](Event<int> &evt) { /*TODO: call rotate */ });
canvas3D->Bind(EVT_GLCANVAS_SCALE_UNIFORMLY, [this](SimpleEvent&) { scale(); });
canvas3D->Bind(EVT_GLCANVAS_INCREASE_OBJECTS, [q](Event<int> &evt) { evt.data == 1 ? q->increase() : q->decrease(); });
#endif // !ENABLE_EXTENDED_SELECTION
canvas3D->Bind(EVT_GLCANVAS_INCREASE_INSTANCES, [q](Event<int> &evt) { evt.data == 1 ? q->increase_instances() : q->decrease_instances(); });
canvas3D->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); });
canvas3D->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this);
canvas3D->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, &priv::on_enable_action_buttons, this);
@ -937,8 +950,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) :
canvas3D->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); } );
canvas3D->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { reset(); });
canvas3D->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { arrange(); });
canvas3D->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase(); });
canvas3D->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease(); });
canvas3D->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase_instances(); });
canvas3D->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease_instances(); });
canvas3D->Bind(EVT_GLTOOLBAR_SPLIT, &priv::on_action_split, this);
canvas3D->Bind(EVT_GLTOOLBAR_CUT, &priv::on_action_cut, this);
#if !ENABLE_EXTENDED_SELECTION
@ -1092,6 +1105,9 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_
// $self->async_apply_config;
} else {
model = Slic3r::Model::read_from_file(path.string(), nullptr, false);
for (auto obj : model.objects)
if (obj->name.empty())
obj->name = fs::path(obj->input_file).filename().string();
}
}
catch (const std::runtime_error &e) {
@ -1139,7 +1155,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_
new_model->convert_multipart_object(nozzle_dmrs->values.size());
}
auto loaded_idxs = load_model_objects(model.objects);
auto loaded_idxs = load_model_objects(new_model->objects);
obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end());
}
@ -1159,7 +1175,7 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode
bool scaled_down = false;
std::vector<size_t> obj_idxs;
#if ENABLE_EXTENDED_SELECTION
unsigned int obj_count = 0;
unsigned int obj_count = model.objects.size();
#endif // ENABLE_EXTENDED_SELECTION
for (ModelObject *model_object : model_objects) {
@ -1238,7 +1254,8 @@ std::unique_ptr<CheckboxFileDialog> Plater::priv::get_export_file(GUI::FileType
case FT_STL:
case FT_AMF:
case FT_3MF:
wildcard = file_wildcards[FT_STL];
case FT_GCODE:
wildcard = file_wildcards[file_type];
break;
default:
@ -1342,7 +1359,7 @@ void Plater::priv::selection_changed()
_3DScene::enable_toolbar_item(canvas3D, "split", have_sel);
_3DScene::enable_toolbar_item(canvas3D, "cut", have_sel);
_3DScene::enable_toolbar_item(canvas3D, "settings", have_sel);
_3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed);
_3DScene::enable_toolbar_item(canvas3D, "layersediting", have_sel && config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D));
#endif // ENABLE_EXTENDED_SELECTION
#if ENABLE_EXTENDED_SELECTION
@ -1421,25 +1438,31 @@ void Plater::priv::object_list_changed()
{
// Enable/disable buttons depending on whether there are any objects on the platter.
#if ENABLE_EXTENDED_SELECTION
const bool have_objects = !model.objects.empty();
_3DScene::enable_toolbar_item(canvas3D, "deleteall", can_delete_all());
_3DScene::enable_toolbar_item(canvas3D, "arrange", can_arrange());
#else
const bool have_objects = !objects.empty();
#endif // ENABLE_EXTENDED_SELECTION
_3DScene::enable_toolbar_item(canvas3D, "deleteall", have_objects);
_3DScene::enable_toolbar_item(canvas3D, "arrange", have_objects);
#endif // ENABLE_EXTENDED_SELECTION
const bool export_in_progress = !(export_gcode_output_file.empty() && send_gcode_file.empty());
// XXX: is this right?
const bool model_fits = _3DScene::check_volumes_outside_state(canvas3D, config) == ModelInstance::PVS_Inside;
#if ENABLE_EXTENDED_SELECTION
sidebar->enable_buttons(!model.objects.empty() && !export_in_progress && model_fits);
#else
sidebar->enable_buttons(have_objects && !export_in_progress && model_fits);
#endif // ENABLE_EXTENDED_SELECTION
}
#if !ENABLE_EXTENDED_SELECTION
void Plater::priv::select_view()
{
// TODO
}
#endif // !ENABLE_EXTENDED_SELECTION
void Plater::priv::remove(size_t obj_idx)
{
@ -1448,6 +1471,9 @@ void Plater::priv::remove(size_t obj_idx)
// Prevent toolpaths preview from rendering while we modify the Print object
preview->set_enabled(false);
if (_3DScene::is_layers_editing_enabled(canvas3D))
_3DScene::enable_layers_editing(canvas3D, false);
#if !ENABLE_EXTENDED_SELECTION
objects.erase(objects.begin() + obj_idx);
#endif // !ENABLE_EXTENDED_SELECTION
@ -1471,6 +1497,9 @@ void Plater::priv::reset()
// Prevent toolpaths preview from rendering while we modify the Print object
preview->set_enabled(false);
if (_3DScene::is_layers_editing_enabled(canvas3D))
_3DScene::enable_layers_editing(canvas3D, false);
#if !ENABLE_EXTENDED_SELECTION
objects.clear();
#endif // !ENABLE_EXTENDED_SELECTION
@ -1487,13 +1516,20 @@ void Plater::priv::reset()
update();
}
#if !ENABLE_EXTENDED_SELECTION
void Plater::priv::rotate()
{
// TODO
}
#endif // !ENABLE_EXTENDED_SELECTION
void Plater::priv::mirror(const Axis &axis)
void Plater::priv::mirror(Axis axis)
{
#if ENABLE_MIRROR
#if ENABLE_EXTENDED_SELECTION
_3DScene::mirror_selection(canvas3D, axis);
#endif // ENABLE_EXTENDED_SELECTION
#else
#if ENABLE_EXTENDED_SELECTION
int obj_idx = get_selected_object_idx();
if (obj_idx == -1)
@ -1526,12 +1562,15 @@ void Plater::priv::mirror(const Axis &axis)
#endif // ENABLE_EXTENDED_SELECTION
selection_changed();
update();
#endif // ENABLE_MIRROR
}
#if !ENABLE_EXTENDED_SELECTION
void Plater::priv::scale()
{
// TODO
}
#endif // !ENABLE_EXTENDED_SELECTION
void Plater::priv::arrange()
{
@ -1547,7 +1586,45 @@ void Plater::priv::arrange()
void Plater::priv::split_object()
{
// TODO
#if ENABLE_EXTENDED_SELECTION
int obj_idx = get_selected_object_idx();
if (obj_idx == -1)
return;
// we clone model object because split_object() adds the split volumes
// into the same model object, thus causing duplicates when we call load_model_objects()
Model new_model = model;
ModelObject* current_model_object = new_model.objects[obj_idx];
if (current_model_object->volumes.size() > 1)
{
Slic3r::GUI::warning_catcher(q, _(L("The selected object can't be split because it contains more than one volume/material.")));
return;
}
// $self->stop_background_process;
ModelObjectPtrs new_objects;
current_model_object->split(&new_objects);
if (new_objects.size() == 1)
{
Slic3r::GUI::warning_catcher(q, _(L("The selected object couldn't be split because it contains only one part.")));
// $self->schedule_background_process;
}
else
{
for (ModelObject* m : new_objects)
{
m->center_around_origin();
}
remove(obj_idx);
// load all model objects at once, otherwise the plate would be rearranged after each one
// causing original positions not to be kept
load_model_objects(new_objects);
}
#endif // ENABLE_EXTENDED_SELECTION
}
void Plater::priv::schedule_background_process()
@ -1821,7 +1898,7 @@ void Plater::priv::on_action_add(SimpleEvent&)
void Plater::priv::on_action_split(SimpleEvent&)
{
// TODO
split_object();
}
void Plater::priv::on_action_cut(SimpleEvent&)
@ -1838,7 +1915,10 @@ void Plater::priv::on_action_settings(SimpleEvent&)
void Plater::priv::on_action_layersediting(SimpleEvent&)
{
// TODO
bool enable = !_3DScene::is_layers_editing_enabled(canvas3D);
_3DScene::enable_layers_editing(canvas3D, enable);
if (enable && !_3DScene::is_layers_editing_enabled(canvas3D))
_3DScene::enable_toolbar_item(canvas3D, "layersediting", false);
}
#if !ENABLE_EXTENDED_SELECTION
@ -1958,17 +2038,41 @@ bool Plater::priv::init_object_menu()
wxMenuItem* item_delete = append_menu_item(&object_menu, wxID_ANY, _(L("Delete\tDel")), _(L("Remove the selected object")),
[this](wxCommandEvent&){ q->remove_selected(); }, "brick_delete.png");
wxMenuItem* item_increase = append_menu_item(&object_menu, wxID_ANY, _(L("Increase copies\t+")), _(L("Place one more copy of the selected object")),
[this](wxCommandEvent&){ q->increase(); }, "add.png");
[this](wxCommandEvent&){ q->increase_instances(); }, "add.png");
wxMenuItem* item_decrease = append_menu_item(&object_menu, wxID_ANY, _(L("Decrease copies\t-")), _(L("Remove one copy of the selected object")),
[this](wxCommandEvent&){ q->decrease(); }, "delete.png");
[this](wxCommandEvent&){ q->decrease_instances(); }, "delete.png");
object_menu.AppendSeparator();
#if ENABLE_MIRROR
wxMenu* mirror_menu = new wxMenu();
if (mirror_menu == nullptr)
return false;
append_menu_item(mirror_menu, wxID_ANY, _(L("Along X axis")), _(L("Mirror the selected object along the X axis")),
[this](wxCommandEvent&){ mirror(X); }, "bullet_red.png", &object_menu);
append_menu_item(mirror_menu, wxID_ANY, _(L("Along Y axis")), _(L("Mirror the selected object along the Y axis")),
[this](wxCommandEvent&){ mirror(Y); }, "bullet_green.png", &object_menu);
append_menu_item(mirror_menu, wxID_ANY, _(L("Along Z axis")), _(L("Mirror the selected object along the Z axis")),
[this](wxCommandEvent&){ mirror(Z); }, "bullet_blue.png", &object_menu);
wxMenuItem* item_mirror = append_submenu(&object_menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object")));
#endif // ENABLE_MIRROR
wxMenuItem* item_split = append_menu_item(&object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual parts")),
[this](wxCommandEvent&){ split_object(); }, "shape_ungroup.png");
#if ENABLE_EXTENDED_SELECTION
// ui updates needs to be binded to the parent panel
if (q != nullptr)
{
#if ENABLE_MIRROR
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId());
#endif // ENABLE_MIRROR
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId());
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId());
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId());
q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_object()); }, item_split->GetId());
}
#endif // ENABLE_EXTENDED_SELECTION
@ -1997,7 +2101,7 @@ bool Plater::priv::can_decrease_instances() const
bool Plater::priv::can_split_object() const
{
int obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts();
}
bool Plater::priv::can_cut_object() const
@ -2008,8 +2112,26 @@ bool Plater::priv::can_cut_object() const
bool Plater::priv::layers_height_allowed() const
{
return config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D);
int obj_idx = get_selected_object_idx();
return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D);
}
bool Plater::priv::can_delete_all() const
{
return !model.objects.empty();
}
bool Plater::priv::can_arrange() const
{
return !model.objects.empty();
}
#if ENABLE_MIRROR
bool Plater::priv::can_mirror() const
{
return get_selection().is_from_single_instance();
}
#endif // ENABLE_MIRROR
#endif // ENABLE_EXTENDED_SELECTION
// Plater / Public
@ -2063,7 +2185,7 @@ void Plater::remove_selected()
#endif // ENABLE_EXTENDED_SELECTION
}
void Plater::increase(size_t num)
void Plater::increase_instances(size_t num)
{
#if ENABLE_EXTENDED_SELECTION
int obj_idx = p->get_selected_object_idx();
@ -2105,12 +2227,16 @@ void Plater::increase(size_t num)
p->update();
}
#if ENABLE_EXTENDED_SELECTION
p->get_selection().add_instance(obj_idx, (int)model_object->instances.size() - 1);
#endif // ENABLE_EXTENDED_SELECTION
p->selection_changed();
this->p->schedule_background_process();
}
void Plater::decrease(size_t num)
void Plater::decrease_instances(size_t num)
{
#if ENABLE_EXTENDED_SELECTION
int obj_idx = p->get_selected_object_idx();
@ -2148,6 +2274,12 @@ void Plater::decrease(size_t num)
}
p->update();
#if ENABLE_EXTENDED_SELECTION
if (!model_object->instances.empty())
p->get_selection().add_instance(obj_idx, (int)model_object->instances.size() - 1);
#endif // ENABLE_EXTENDED_SELECTION
p->selection_changed();
// $self->schedule_background_process;
@ -2169,11 +2301,10 @@ void Plater::set_number_of_copies(size_t num)
#endif // ENABLE_EXTENDED_SELECTION
int diff = (int)num - (int)model_object->instances.size();
if (diff > 0) {
increase(diff);
} else if (diff < 0) {
decrease(-diff);
}
if (diff > 0)
increase_instances(diff);
else if (diff < 0)
decrease_instances(-diff);
}
fs::path Plater::export_gcode(const fs::path &output_path)

View file

@ -113,8 +113,8 @@ public:
void remove(size_t obj_idx);
void remove_selected();
void increase(size_t num = 1);
void decrease(size_t num = 1);
void increase_instances(size_t num = 1);
void decrease_instances(size_t num = 1);
void set_number_of_copies(size_t num);
// Note: empty path means "use the default"

View file

@ -476,14 +476,14 @@ void Tab::get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool
void Tab::update_changed_tree_ui()
{
auto cur_item = m_treectrl->GetFirstVisibleItem();
if (!m_treectrl->IsVisible(cur_item))
if (!cur_item || !m_treectrl->IsVisible(cur_item))
return;
auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
while (cur_item){
auto title = m_treectrl->GetItemText(cur_item);
for (auto page : m_pages)
{
if (page->title() != title)
if (page->title() != title)
continue;
bool sys_page = true;
bool modified_page = false;
@ -632,6 +632,25 @@ void Tab::reload_config(){
Thaw();
}
void Tab::update_visibility(ConfigOptionMode mode)
{
Freeze();
for (auto page : m_pages)
page->update_visibility(mode);
update_page_tree_visibility();
m_hsizer->Layout();
Refresh();
Thaw();
// to update tree items color
wxTheApp->CallAfter([this]() {
update_changed_tree_ui();
});
}
Field* Tab::get_field(const t_config_option_key& opt_key, int opt_index/* = -1*/) const
{
Field* field = nullptr;
@ -1021,7 +1040,7 @@ void TabPrint::build()
page = add_options_page(_(L("Dependencies")), "wrench.png");
optgroup = page->new_optgroup(_(L("Profile dependencies")));
line = { _(L("Compatible printers")), "" };
line = optgroup->create_single_option_line("compatible_printers");//{ _(L("Compatible printers")), "" };
line.widget = [this](wxWindow* parent){
return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn);
};
@ -1347,7 +1366,7 @@ void TabFilament::build()
optgroup->append_single_option_line("filament_cooling_final_speed");
optgroup->append_single_option_line("filament_minimal_purge_on_wipe_tower");
line = { _(L("Ramming")), "" };
line = optgroup->create_single_option_line("filament_ramming_parameters");// { _(L("Ramming")), "" };
line.widget = [this](wxWindow* parent){
auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
auto sizer = new wxBoxSizer(wxHORIZONTAL);
@ -1387,7 +1406,7 @@ void TabFilament::build()
page = add_options_page(_(L("Dependencies")), "wrench.png");
optgroup = page->new_optgroup(_(L("Profile dependencies")));
line = { _(L("Compatible printers")), "" };
line = optgroup->create_single_option_line("compatible_printers");//{ _(L("Compatible printers")), "" };
line.widget = [this](wxWindow* parent){
return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn);
};
@ -1482,7 +1501,7 @@ void TabPrinter::build_fff()
auto page = add_options_page(_(L("General")), "printer_empty.png");
auto optgroup = page->new_optgroup(_(L("Size and coordinates")));
Line line{ _(L("Bed shape")), "" };
Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" };
line.widget = [this](wxWindow* parent){
auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
btn->SetFont(wxGetApp().small_font());
@ -1514,6 +1533,7 @@ void TabPrinter::build_fff()
def.label = L("Extruders");
def.tooltip = L("Number of extruders of the printer.");
def.min = 1;
def.mode = comExpert;
Option option(def, "extruders_count");
optgroup->append_single_option_line(option);
optgroup->append_single_option_line("single_extruder_multi_material");
@ -1767,7 +1787,7 @@ void TabPrinter::build_sla()
auto page = add_options_page(_(L("General")), "printer_empty.png");
auto optgroup = page->new_optgroup(_(L("Size and coordinates")));
Line line{ _(L("Bed shape")), "" };
Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" };
line.widget = [this](wxWindow* parent){
auto btn = new wxButton(parent, wxID_ANY, _(L(" Set ")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
// btn->SetFont(Slic3r::GUI::small_font);
@ -2255,6 +2275,33 @@ void Tab::rebuild_page_tree(bool tree_sel_change_event /*= false*/)
Thaw();
}
void Tab::update_page_tree_visibility()
{
const auto sel_item = m_treectrl->GetSelection();
const auto selected = sel_item ? m_treectrl->GetItemText(sel_item) : "";
const auto rootItem = m_treectrl->GetRootItem();
auto have_selection = 0;
m_treectrl->DeleteChildren(rootItem);
for (auto p : m_pages)
{
if (!p->get_show())
continue;
auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID());
m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
if (p->title() == selected) {
m_treectrl->SelectItem(itemId);
have_selection = 1;
}
}
if (!have_selection) {
// this is triggered on first load, so we don't disable the sel change event
m_treectrl->SelectItem(m_treectrl->GetFirstVisibleItem());//! (treectrl->GetFirstChild(rootItem));
}
}
// Called by the UI combo box when the user switches profiles.
// Select a preset by a name.If !defined(name), then the default preset is selected.
// If the current profile is modified, user is asked to save the changes.
@ -2379,10 +2426,13 @@ void Tab::OnTreeSelChange(wxTreeEvent& event)
wxWindowUpdateLocker noUpdates(this);
#endif
if (m_pages.empty())
return;
Page* page = nullptr;
const auto sel_item = m_treectrl->GetSelection();
const auto selection = sel_item ? m_treectrl->GetItemText(sel_item) : "";
for (auto p : m_pages)
for (auto p : m_pages)
if (p->title() == selection)
{
page = p.get();
@ -2681,6 +2731,15 @@ void Page::reload_config()
group->reload_config();
}
void Page::update_visibility(ConfigOptionMode mode)
{
bool ret_val = false;
for (auto group : m_optgroups)
ret_val = group->update_visibility(mode) || ret_val;
m_show = ret_val;
}
Field* Page::get_field(const t_config_option_key& opt_key, int opt_index /*= -1*/) const
{
Field* field = nullptr;
@ -2704,8 +2763,22 @@ bool Page::set_value(const t_config_option_key& opt_key, const boost::any& value
// package Slic3r::GUI::Tab::Page;
ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_label_width /*= -1*/)
{
auto extra_column = [](wxWindow* parent, const Line& line)
{
std::string bmp_name;
if (line.get_options().size() == 0)
bmp_name = "error.png";
else {
auto mode = line.get_options()[0].opt.mode; //we assume that we have one option per line
bmp_name = mode == comExpert ? "mode_expert_.png" :
mode == comMiddle ? "mode_middle_.png" : "mode_simple_.png";
}
auto bmp = new wxStaticBitmap(parent, wxID_ANY, wxBitmap(from_u8(var(bmp_name)), wxBITMAP_TYPE_PNG));
return bmp;
};
//! config_ have to be "right"
ConfigOptionsGroupShp optgroup = std::make_shared<ConfigOptionsGroup>(this, title, m_config, true);
ConfigOptionsGroupShp optgroup = std::make_shared<ConfigOptionsGroup>(this, title, m_config, true, extra_column);
if (noncommon_label_width >= 0)
optgroup->label_width = noncommon_label_width;
@ -2844,7 +2917,7 @@ void TabSLAMaterial::build()
page = add_options_page(_(L("Dependencies")), "wrench.png");
optgroup = page->new_optgroup(_(L("Profile dependencies")));
auto line = Line { _(L("Compatible printers")), "" };
Line line = optgroup->create_single_option_line("compatible_printers");//Line { _(L("Compatible printers")), "" };
line.widget = [this](wxWindow* parent){
return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn);
};

View file

@ -47,6 +47,7 @@ class Page : public wxScrolledWindow
wxString m_title;
size_t m_iconID;
wxBoxSizer* m_vsizer;
bool m_show = true;
public:
Page(wxWindow* parent, const wxString title, const int iconID) :
m_parent(parent),
@ -73,6 +74,7 @@ public:
size_t iconID() const { return m_iconID; }
void set_config(DynamicPrintConfig* config_in) { m_config = config_in; }
void reload_config();
void update_visibility(ConfigOptionMode mode);
Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const;
bool set_value(const t_config_option_key& opt_key, const boost::any& value);
ConfigOptionsGroupShp new_optgroup(const wxString& title, int noncommon_label_width = -1);
@ -88,6 +90,7 @@ public:
const wxColour get_item_colour() {
return *m_item_color;
}
bool get_show() const { return m_show; }
protected:
// Color of TreeCtrlItem. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
@ -214,6 +217,7 @@ public:
void create_preset_tab();
void load_current_preset();
void rebuild_page_tree(bool tree_sel_change_event = false);
void update_page_tree_visibility();
void select_preset(std::string preset_name = "");
bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = "");
wxSizer* compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn);
@ -249,6 +253,7 @@ public:
void update_tab_ui();
void load_config(const DynamicPrintConfig& config);
virtual void reload_config();
void update_visibility(ConfigOptionMode mode);
Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const;
bool set_value(const t_config_option_key& opt_key, const boost::any& value);
wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText);

View file

@ -11,7 +11,7 @@
#include "GUI_ObjectList.hpp"
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, const std::string& icon)
std::function<void(wxCommandEvent& event)> cb, const std::string& icon, wxEvtHandler* event_handler)
{
if (id == wxID_ANY)
id = wxNewId();
@ -20,7 +20,26 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const
if (!icon.empty())
item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG));
menu->Bind(wxEVT_MENU, cb, id);
if (event_handler != nullptr)
event_handler->Bind(wxEVT_MENU, cb, id);
else
menu->Bind(wxEVT_MENU, cb, id);
return item;
}
wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, const std::string& icon)
{
if (id == wxID_ANY)
id = wxNewId();
wxMenuItem* item = new wxMenuItem(menu, id, string, description);
if (!icon.empty())
item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG));
item->SetSubMenu(sub_menu);
menu->Append(item);
return item;
}
@ -770,7 +789,7 @@ void PrusaObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType&
type = itUndef;
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID();
if (!node || node->GetIdx() < 0 && node->GetType() != itObject)
if (!node || node->GetIdx() < 0 && !(node->GetType() & (itObject|itSettings|itInstanceRoot)))
return;
idx = node->GetIdx();

View file

@ -12,9 +12,12 @@
#include <vector>
#include <set>
#include <functional>
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, const std::string& icon = "");
std::function<void(wxCommandEvent& event)> cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr);
wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, const std::string& icon = "");
class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup
{
@ -259,7 +262,10 @@ public:
m_name = "Settings to modified";
}
else if (type == itInstanceRoot) {
m_name = "Instances";
m_name = "Instances";
#ifdef __WXGTK__
m_container = true;
#endif //__WXGTK__
}
else if (type == itInstance) {
m_idx = parent->GetChildCount();