Merge branch 'dev_native' of https://github.com/prusa3d/Slic3r into dev_native

This commit is contained in:
bubnikv 2018-10-31 16:25:55 +01:00
commit 7e71aaffd5
36 changed files with 1313 additions and 565 deletions

View file

@ -1,3 +1,4 @@
#include "libslic3r.h"
#include "Geometry.hpp" #include "Geometry.hpp"
#include "ClipperUtils.hpp" #include "ClipperUtils.hpp"
#include "ExPolygon.hpp" #include "ExPolygon.hpp"
@ -369,12 +370,6 @@ contains(const std::vector<T> &vector, const Point &point)
} }
template bool contains(const ExPolygons &vector, const Point &point); template bool contains(const ExPolygons &vector, const Point &point);
double
rad2deg(double angle)
{
return angle / PI * 180.0;
}
double double
rad2deg_dir(double angle) rad2deg_dir(double angle)
{ {
@ -1232,4 +1227,161 @@ Vec3d extract_euler_angles(const Transform3d& transform)
return extract_euler_angles(m); return extract_euler_angles(m);
} }
#if ENABLE_MODELVOLUME_TRANSFORM
Transformation::Flags::Flags()
: dont_translate(true)
, dont_rotate(true)
, dont_scale(true)
#if ENABLE_MIRROR
, dont_mirror(true)
#endif // ENABLE_MIRROR
{
}
#if ENABLE_MIRROR
bool Transformation::Flags::needs_update(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
{
return (this->dont_translate != dont_translate) || (this->dont_rotate != dont_rotate) || (this->dont_scale != dont_scale) || (this->dont_mirror != dont_mirror);
}
void Transformation::Flags::set(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror)
{
this->dont_translate = dont_translate;
this->dont_rotate = dont_rotate;
this->dont_scale = dont_scale;
this->dont_mirror = dont_mirror;
}
#else
bool Transformation::Flags::needs_update(bool dont_translate, bool dont_rotate, bool dont_scale) const
{
return (this->dont_translate != dont_translate) || (this->dont_rotate != dont_rotate) || (this->dont_scale != dont_scale);
}
void Transformation::Flags::set(bool dont_translate, bool dont_rotate, bool dont_scale)
{
this->dont_translate = dont_translate;
this->dont_rotate = dont_rotate;
this->dont_scale = dont_scale;
}
#endif // ENABLE_MIRROR
Transformation::Transformation()
: m_offset(Vec3d::Zero())
, m_rotation(Vec3d::Zero())
, m_scaling_factor(Vec3d::Ones())
#if ENABLE_MIRROR
, m_mirror(Vec3d::Ones())
#endif // ENABLE_MIRROR
, m_matrix(Transform3d::Identity())
, m_dirty(false)
{
}
void Transformation::set_offset(const Vec3d& offset)
{
set_offset(X, offset(0));
set_offset(Y, offset(1));
set_offset(Z, offset(2));
}
void Transformation::set_offset(Axis axis, double offset)
{
if (m_offset(axis) != offset)
{
m_offset(axis) = offset;
m_dirty = true;
}
}
void Transformation::set_rotation(const Vec3d& rotation)
{
set_rotation(X, rotation(0));
set_rotation(Y, rotation(1));
set_rotation(Z, rotation(2));
}
void Transformation::set_rotation(Axis axis, double rotation)
{
rotation = angle_to_0_2PI(rotation);
if (m_rotation(axis) = rotation)
{
m_rotation(axis) = rotation;
m_dirty = true;
}
}
void Transformation::set_scaling_factor(const Vec3d& scaling_factor)
{
set_scaling_factor(X, scaling_factor(0));
set_scaling_factor(Y, scaling_factor(1));
set_scaling_factor(Z, scaling_factor(2));
}
void Transformation::set_scaling_factor(Axis axis, double scaling_factor)
{
if (m_scaling_factor(axis) != std::abs(scaling_factor))
{
m_scaling_factor(axis) = std::abs(scaling_factor);
m_dirty = true;
}
}
void Transformation::set_mirror(const Vec3d& mirror)
{
set_mirror(X, mirror(0));
set_mirror(Y, mirror(1));
set_mirror(Z, mirror(2));
}
void Transformation::set_mirror(Axis axis, double mirror)
{
double abs_mirror = std::abs(mirror);
if (abs_mirror == 0.0)
mirror = 1.0;
else if (abs_mirror != 1.0)
mirror /= abs_mirror;
if (m_mirror(axis) != mirror)
{
m_mirror(axis) = mirror;
m_dirty = true;
}
}
#if ENABLE_MIRROR
const Transform3d& Transformation::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
#else
const Transform3d& Transformation::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale) const
#endif // ENABLE_MIRROR
{
#if ENABLE_MIRROR
if (m_dirty || m_flags.needs_update(dont_translate, dont_rotate, dont_scale, dont_mirror))
#else
if (m_dirty || m_flags.needs_update(dont_translate, dont_rotate, dont_scale))
#endif // ENABLE_MIRROR
{
Vec3d translation = dont_translate ? Vec3d::Zero() : m_offset;
Vec3d rotation = dont_rotate ? Vec3d::Zero() : m_rotation;
Vec3d scale = dont_scale ? Vec3d::Ones() : m_scaling_factor;
#if ENABLE_MIRROR
Vec3d mirror = dont_mirror ? Vec3d::Ones() : m_mirror;
m_matrix = Geometry::assemble_transform(translation, rotation, scale, mirror);
#else
m_matrix = Geometry::assemble_transform(translation, rotation, scale);
#endif // ENABLE_MIRROR
#if ENABLE_MIRROR
m_flags.set(dont_translate, dont_rotate, dont_scale, dont_mirror);
#else
m_flags.set(dont_translate, dont_rotate, dont_scale);
#endif // ENABLE_MIRROR
m_dirty = false;
}
return m_matrix;
}
#endif // ENABLE_MODELVOLUME_TRANSFORM
} } } }

View file

@ -117,9 +117,23 @@ void chained_path(const Points &points, std::vector<Points::size_type> &retval);
template<class T> void chained_path_items(Points &points, T &items, T &retval); template<class T> void chained_path_items(Points &points, T &items, T &retval);
bool directions_parallel(double angle1, double angle2, double max_diff = 0); bool directions_parallel(double angle1, double angle2, double max_diff = 0);
template<class T> bool contains(const std::vector<T> &vector, const Point &point); template<class T> bool contains(const std::vector<T> &vector, const Point &point);
double rad2deg(double angle); template<typename T> T rad2deg(T angle) { return T(180.0) * angle / T(PI); }
double rad2deg_dir(double angle); double rad2deg_dir(double angle);
template<typename T> T deg2rad(T angle) { return T(PI) * angle / T(180.0); } template<typename T> T deg2rad(T angle) { return T(PI) * angle / T(180.0); }
template<typename T> T angle_to_0_2PI(T angle)
{
static const T TWO_PI = T(2) * T(PI);
while (angle < T(0))
{
angle += TWO_PI;
}
while (TWO_PI < angle)
{
angle -= TWO_PI;
}
return angle;
}
void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval); void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval);
double linint(double value, double oldmin, double oldmax, double newmin, double newmax); double linint(double value, double oldmin, double oldmax, double newmin, double newmax);
@ -200,6 +214,79 @@ Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>&
// Returns the euler angles extracted from the given affine transform // Returns the euler angles extracted from the given affine transform
// Warning -> The transform should not contain any shear !!! // Warning -> The transform should not contain any shear !!!
Vec3d extract_euler_angles(const Transform3d& transform); Vec3d extract_euler_angles(const Transform3d& transform);
#if ENABLE_MODELVOLUME_TRANSFORM
class Transformation
{
struct Flags
{
bool dont_translate;
bool dont_rotate;
bool dont_scale;
#if ENABLE_MIRROR
bool dont_mirror;
#endif // ENABLE_MIRROR
Flags();
#if ENABLE_MIRROR
bool needs_update(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const;
void set(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror);
#else
bool needs_update(bool dont_translate, bool dont_rotate, bool dont_scale) const;
void set(bool dont_translate, bool dont_rotate, bool dont_scale);
#endif // ENABLE_MIRROR
};
Vec3d m_offset; // In unscaled coordinates
Vec3d m_rotation; // Rotation around the three axes, in radians around mesh center point
Vec3d m_scaling_factor; // Scaling factors along the three axes
#if ENABLE_MIRROR
Vec3d m_mirror; // Mirroring along the three axes
#endif // ENABLE_MIRROR
mutable Transform3d m_matrix;
mutable Flags m_flags;
mutable bool m_dirty;
public:
Transformation();
const Vec3d& get_offset() const { return m_offset; }
double get_offset(Axis axis) const { return m_offset(axis); }
void set_offset(const Vec3d& offset);
void set_offset(Axis axis, double offset);
const Vec3d& get_rotation() const { return m_rotation; }
double get_rotation(Axis axis) const { return m_rotation(axis); }
void set_rotation(const Vec3d& rotation);
void set_rotation(Axis axis, double rotation);
Vec3d get_scaling_factor() const { return m_scaling_factor; }
double get_scaling_factor(Axis axis) const { return m_scaling_factor(axis); }
#if ENABLE_MIRROR
void set_scaling_factor(const Vec3d& scaling_factor);
void set_scaling_factor(Axis axis, double scaling_factor);
const Vec3d& get_mirror() const { return m_mirror; }
double get_mirror(Axis axis) const { return m_mirror(axis); }
void set_mirror(const Vec3d& mirror);
void set_mirror(Axis axis, double mirror);
const Transform3d& world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const;
#else
void set_scaling_factor(const Vec3d& scaling_factor) { m_scaling_factor = scaling_factor; }
void set_scaling_factor(Axis axis, double scaling_factor) { m_scaling_factor(axis) = scaling_factor; }
const Transform3d& world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false) const;
#endif // ENABLE_MIRROR
};
#endif // ENABLE_MODELVOLUME_TRANSFORM
} } } }
#endif #endif

View file

@ -712,18 +712,32 @@ void ModelObject::center_around_origin()
if (!this->instances.empty()) { if (!this->instances.empty()) {
for (ModelInstance *i : this->instances) { for (ModelInstance *i : this->instances) {
#if ENABLE_MIRROR
i->set_offset(i->get_offset() - shift); i->set_offset(i->get_offset() - shift);
#else
// apply rotation and scaling to vector as well before translating instance,
// in order to leave final position unaltered
i->set_offset(i->get_offset() + i->transform_vector(-shift, true));
#endif // ENABLE_MIRROR
} }
this->invalidate_bounding_box(); this->invalidate_bounding_box();
} }
} }
void ModelObject::ensure_on_bed()
{
translate_instances(Vec3d(0.0, 0.0, -get_min_z()));
}
void ModelObject::translate_instances(const Vec3d& vector)
{
for (size_t i = 0; i < instances.size(); ++i)
{
translate_instance(i, vector);
}
}
void ModelObject::translate_instance(size_t instance_idx, const Vec3d& vector)
{
ModelInstance* i = instances[instance_idx];
i->set_offset(i->get_offset() + vector);
invalidate_bounding_box();
}
void ModelObject::translate(coordf_t x, coordf_t y, coordf_t z) void ModelObject::translate(coordf_t x, coordf_t y, coordf_t z)
{ {
for (ModelVolume *v : this->volumes) for (ModelVolume *v : this->volumes)
@ -895,6 +909,42 @@ void ModelObject::repair()
v->mesh.repair(); v->mesh.repair();
} }
double ModelObject::get_min_z() const
{
if (instances.empty())
return 0.0;
else
{
double min_z = DBL_MAX;
for (size_t i = 0; i < instances.size(); ++i)
{
min_z = std::min(min_z, get_instance_min_z(i));
}
return min_z;
}
}
double ModelObject::get_instance_min_z(size_t instance_idx) const
{
double min_z = DBL_MAX;
ModelInstance* inst = instances[instance_idx];
const Transform3d& m = inst->world_matrix(true);
for (ModelVolume *v : volumes)
{
for (uint32_t f = 0; f < v->mesh.stl.stats.number_of_facets; ++f)
{
const stl_facet* facet = v->mesh.stl.facet_start + f;
min_z = std::min(min_z, Vec3d::UnitZ().dot(m * facet->vertex[0].cast<double>()));
min_z = std::min(min_z, Vec3d::UnitZ().dot(m * facet->vertex[1].cast<double>()));
min_z = std::min(min_z, Vec3d::UnitZ().dot(m * facet->vertex[2].cast<double>()));
}
}
return min_z + inst->get_offset(Z);
}
unsigned int ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_volume) unsigned int ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_volume)
{ {
unsigned int num_printable = 0; unsigned int num_printable = 0;
@ -1074,6 +1124,7 @@ size_t ModelVolume::split(unsigned int max_extruders)
return idx; return idx;
} }
#if !ENABLE_MODELVOLUME_TRANSFORM
void ModelInstance::set_rotation(const Vec3d& rotation) void ModelInstance::set_rotation(const Vec3d& rotation)
{ {
set_rotation(X, rotation(0)); set_rotation(X, rotation(0));
@ -1126,6 +1177,7 @@ void ModelInstance::set_mirror(Axis axis, double mirror)
m_mirror(axis) = mirror; m_mirror(axis) = mirror;
} }
#endif // ENABLE_MIRROR #endif // ENABLE_MIRROR
#endif // !ENABLE_MODELVOLUME_TRANSFORM
void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
{ {
@ -1136,24 +1188,40 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mes
{ {
// Rotate around mesh origin. // Rotate around mesh origin.
TriangleMesh copy(*mesh); TriangleMesh copy(*mesh);
#if ENABLE_MIRROR
copy.transform(world_matrix(true, false, true, true).cast<float>());
#else
copy.transform(world_matrix(true, false, true).cast<float>()); copy.transform(world_matrix(true, false, true).cast<float>());
#endif // ENABLE_MIRROR
BoundingBoxf3 bbox = copy.bounding_box(); BoundingBoxf3 bbox = copy.bounding_box();
if (!empty(bbox)) { if (!empty(bbox)) {
// Scale the bounding box along the three axes. // Scale the bounding box along the three axes.
for (unsigned int i = 0; i < 3; ++i) for (unsigned int i = 0; i < 3; ++i)
{ {
#if ENABLE_MODELVOLUME_TRANSFORM
if (std::abs(m_transformation.get_scaling_factor((Axis)i)-1.0) > EPSILON)
{
bbox.min(i) *= m_transformation.get_scaling_factor((Axis)i);
bbox.max(i) *= m_transformation.get_scaling_factor((Axis)i);
#else
if (std::abs(this->m_scaling_factor(i) - 1.0) > EPSILON) if (std::abs(this->m_scaling_factor(i) - 1.0) > EPSILON)
{ {
bbox.min(i) *= this->m_scaling_factor(i); bbox.min(i) *= this->m_scaling_factor(i);
bbox.max(i) *= this->m_scaling_factor(i); bbox.max(i) *= this->m_scaling_factor(i);
#endif // ENABLE_MODELVOLUME_TRANSFORM
} }
} }
// Translate the bounding box. // Translate the bounding box.
if (! dont_translate) { if (! dont_translate) {
#if ENABLE_MODELVOLUME_TRANSFORM
bbox.min += m_transformation.get_offset();
bbox.max += m_transformation.get_offset();
#else
bbox.min += this->m_offset; bbox.min += this->m_offset;
bbox.max += this->m_offset; bbox.max += this->m_offset;
#endif // ENABLE_MODELVOLUME_TRANSFORM
} }
} }
return bbox; return bbox;
@ -1171,12 +1239,20 @@ Vec3d ModelInstance::transform_vector(const Vec3d& v, bool dont_translate) const
void ModelInstance::transform_polygon(Polygon* polygon) const void ModelInstance::transform_polygon(Polygon* polygon) const
{ {
#if ENABLE_MODELVOLUME_TRANSFORM
// CHECK_ME -> Is the following correct or it should take in account all three rotations ?
polygon->rotate(m_transformation.get_rotation(Z)); // rotate around polygon origin
// CHECK_ME -> Is the following correct ?
polygon->scale(m_transformation.get_scaling_factor(X), m_transformation.get_scaling_factor(Y)); // scale around polygon origin
#else
// CHECK_ME -> Is the following correct or it should take in account all three rotations ? // CHECK_ME -> Is the following correct or it should take in account all three rotations ?
polygon->rotate(this->m_rotation(2)); // rotate around polygon origin polygon->rotate(this->m_rotation(2)); // rotate around polygon origin
// CHECK_ME -> Is the following correct ? // CHECK_ME -> Is the following correct ?
polygon->scale(this->m_scaling_factor(0), this->m_scaling_factor(1)); // scale around polygon origin polygon->scale(this->m_scaling_factor(0), this->m_scaling_factor(1)); // scale around polygon origin
#endif // ENABLE_MODELVOLUME_TRANSFORM
} }
#if !ENABLE_MODELVOLUME_TRANSFORM
#if ENABLE_MIRROR #if ENABLE_MIRROR
Transform3d ModelInstance::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const Transform3d ModelInstance::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
#else #else
@ -1193,5 +1269,6 @@ Transform3d ModelInstance::world_matrix(bool dont_translate, bool dont_rotate, b
return Geometry::assemble_transform(translation, rotation, scale); return Geometry::assemble_transform(translation, rotation, scale);
#endif // ENABLE_MIRROR #endif // ENABLE_MIRROR
} }
#endif // !ENABLE_MODELVOLUME_TRANSFORM
} }

View file

@ -11,6 +11,9 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#if ENABLE_MODELVOLUME_TRANSFORM
#include "Geometry.hpp"
#endif // ENABLE_MODELVOLUME_TRANSFORM
namespace Slic3r { namespace Slic3r {
@ -153,6 +156,9 @@ public:
// A snug bounding box around the transformed non-modifier object volumes. // A snug bounding box around the transformed non-modifier object volumes.
BoundingBoxf3 instance_bounding_box(size_t instance_idx, bool dont_translate = false) const; BoundingBoxf3 instance_bounding_box(size_t instance_idx, bool dont_translate = false) const;
void center_around_origin(); void center_around_origin();
void ensure_on_bed();
void translate_instances(const Vec3d& vector);
void translate_instance(size_t instance_idx, const Vec3d& vector);
void translate(const Vec3d &vector) { this->translate(vector(0), vector(1), vector(2)); } void translate(const Vec3d &vector) { this->translate(vector(0), vector(1), vector(2)); }
void translate(coordf_t x, coordf_t y, coordf_t z); void translate(coordf_t x, coordf_t y, coordf_t z);
void scale(const Vec3d &versor); void scale(const Vec3d &versor);
@ -167,6 +173,9 @@ public:
void split(ModelObjectPtrs* new_objects); void split(ModelObjectPtrs* new_objects);
void repair(); void repair();
double get_min_z() const;
double get_instance_min_z(size_t instance_idx) const;
// Called by Print::validate() from the UI thread. // Called by Print::validate() from the UI thread.
unsigned int check_instances_print_volume_state(const BoundingBoxf3& print_volume); unsigned int check_instances_print_volume_state(const BoundingBoxf3& print_volume);
@ -204,6 +213,10 @@ class ModelVolume : public ModelBase
// The convex hull of this model's mesh. // The convex hull of this model's mesh.
TriangleMesh m_convex_hull; TriangleMesh m_convex_hull;
#if ENABLE_MODELVOLUME_TRANSFORM
Geometry::Transformation m_transformation;
#endif // ENABLE_MODELVOLUME_TRANSFORM
public: public:
std::string name; std::string name;
// The triangular model. // The triangular model.
@ -251,6 +264,34 @@ public:
static Type type_from_string(const std::string &s); static Type type_from_string(const std::string &s);
static std::string type_to_string(const Type t); static std::string type_to_string(const Type t);
#if ENABLE_MODELVOLUME_TRANSFORM
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }
void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); }
void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); }
const Vec3d& get_rotation() const { return m_transformation.get_rotation(); }
double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); }
void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); }
void set_rotation(Axis axis, double rotation) { m_transformation.set_rotation(axis, rotation); }
Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); }
double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); }
void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); }
void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); }
#if ENABLE_MIRROR
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); }
void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); }
#endif // ENABLE_MIRROR
#endif // ENABLE_MODELVOLUME_TRANSFORM
private: private:
// Parent object owning this ModelVolume. // Parent object owning this ModelVolume.
ModelObject* object; ModelObject* object;
@ -300,12 +341,16 @@ public:
friend class ModelObject; friend class ModelObject;
private: private:
#if ENABLE_MODELVOLUME_TRANSFORM
Geometry::Transformation m_transformation;
#else
Vec3d m_offset; // in unscaled coordinates Vec3d m_offset; // in unscaled coordinates
Vec3d m_rotation; // Rotation around the three axes, in radians around mesh center point Vec3d m_rotation; // Rotation around the three axes, in radians around mesh center point
Vec3d m_scaling_factor; // Scaling factors along the three axes Vec3d m_scaling_factor; // Scaling factors along the three axes
#if ENABLE_MIRROR #if ENABLE_MIRROR
Vec3d m_mirror; // Mirroring along the three axes Vec3d m_mirror; // Mirroring along the three axes
#endif // ENABLE_MIRROR #endif // ENABLE_MIRROR
#endif // ENABLE_MODELVOLUME_TRANSFORM
public: public:
// flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state()) // flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state())
@ -313,6 +358,36 @@ public:
ModelObject* get_object() const { return this->object; } ModelObject* get_object() const { return this->object; }
#if ENABLE_MODELVOLUME_TRANSFORM
const Geometry::Transformation& get_transformation() const { return m_transformation; }
void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; }
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }
void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); }
void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); }
const Vec3d& get_rotation() const { return m_transformation.get_rotation(); }
double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); }
void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); }
void set_rotation(Axis axis, double rotation) { m_transformation.set_rotation(axis, rotation); }
Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); }
double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); }
void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); }
void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); }
#if ENABLE_MIRROR
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); }
void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); }
#endif // ENABLE_MIRROR
#else
const Vec3d& get_offset() const { return m_offset; } const Vec3d& get_offset() const { return m_offset; }
double get_offset(Axis axis) const { return m_offset(axis); } double get_offset(Axis axis) const { return m_offset(axis); }
@ -343,6 +418,7 @@ public:
void set_mirror(const Vec3d& mirror); void set_mirror(const Vec3d& mirror);
void set_mirror(Axis axis, double mirror); void set_mirror(Axis axis, double mirror);
#endif // ENABLE_MIRROR #endif // ENABLE_MIRROR
#endif // ENABLE_MODELVOLUME_TRANSFORM
// To be called on an external mesh // To be called on an external mesh
void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const; void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const;
@ -355,11 +431,19 @@ public:
// To be called on an external polygon. It does not translate the polygon, only rotates and scales. // To be called on an external polygon. It does not translate the polygon, only rotates and scales.
void transform_polygon(Polygon* polygon) const; void transform_polygon(Polygon* polygon) const;
#if ENABLE_MODELVOLUME_TRANSFORM
#if ENABLE_MIRROR
const Transform3d& world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.world_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
#else
const Transform3d& world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false) const { return m_transformation.world_matrix(dont_translate, dont_rotate, dont_scale); }
#endif // ENABLE_MIRROR
#else
#if ENABLE_MIRROR #if ENABLE_MIRROR
Transform3d world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const; Transform3d world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const;
#else #else
Transform3d world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false) const; Transform3d world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false) const;
#endif // ENABLE_MIRROR #endif // ENABLE_MIRROR
#endif // ENABLE_MODELVOLUME_TRANSFORM
bool is_printable() const { return print_volume_state == PVS_Inside; } bool is_printable() const { return print_volume_state == PVS_Inside; }
@ -367,6 +451,11 @@ private:
// Parent object, owning this instance. // Parent object, owning this instance.
ModelObject* object; ModelObject* object;
#if ENABLE_MODELVOLUME_TRANSFORM
ModelInstance(ModelObject *object) : object(object), print_volume_state(PVS_Inside) {}
ModelInstance(ModelObject *object, const ModelInstance &other) :
m_transformation(other.m_transformation), object(object), print_volume_state(PVS_Inside) {}
#else
#if ENABLE_MIRROR #if ENABLE_MIRROR
ModelInstance(ModelObject *object) : m_offset(Vec3d::Zero()), m_rotation(Vec3d::Zero()), m_scaling_factor(Vec3d::Ones()), m_mirror(Vec3d::Ones()), object(object), print_volume_state(PVS_Inside) {} ModelInstance(ModelObject *object) : m_offset(Vec3d::Zero()), m_rotation(Vec3d::Zero()), m_scaling_factor(Vec3d::Ones()), m_mirror(Vec3d::Ones()), object(object), print_volume_state(PVS_Inside) {}
ModelInstance(ModelObject *object, const ModelInstance &other) : ModelInstance(ModelObject *object, const ModelInstance &other) :
@ -376,6 +465,7 @@ private:
ModelInstance(ModelObject *object, const ModelInstance &other) : ModelInstance(ModelObject *object, const ModelInstance &other) :
m_rotation(other.m_rotation), m_scaling_factor(other.m_scaling_factor), m_offset(other.m_offset), object(object), print_volume_state(PVS_Inside) {} m_rotation(other.m_rotation), m_scaling_factor(other.m_scaling_factor), m_offset(other.m_offset), object(object), print_volume_state(PVS_Inside) {}
#endif // ENABLE_MIRROR #endif // ENABLE_MIRROR
#endif // ENABLE_MODELVOLUME_TRANSFORM
explicit ModelInstance(ModelInstance &rhs) = delete; explicit ModelInstance(ModelInstance &rhs) = delete;
ModelInstance& operator=(ModelInstance &rhs) = delete; ModelInstance& operator=(ModelInstance &rhs) = delete;

View file

@ -19,10 +19,13 @@
#define ENABLE_USE_UNIQUE_GLCONTEXT (1 && ENABLE_1_42_0) #define ENABLE_USE_UNIQUE_GLCONTEXT (1 && ENABLE_1_42_0)
// New selections // New selections
#define ENABLE_EXTENDED_SELECTION (1 && ENABLE_1_42_0) #define ENABLE_EXTENDED_SELECTION (1 && ENABLE_1_42_0)
#define DISABLE_INSTANCES_SYNCH (1 && ENABLE_EXTENDED_SELECTION)
// Add mirror components along the three axes in ModelInstance and GLVolume // Add mirror components along the three axes in ModelInstance and GLVolume
#define ENABLE_MIRROR (1 && ENABLE_1_42_0) #define ENABLE_MIRROR (1 && ENABLE_1_42_0)
// Modified camera target behavior // Modified camera target behavior
#define ENABLE_MODIFIED_CAMERA_TARGET (1 && ENABLE_1_42_0) #define ENABLE_MODIFIED_CAMERA_TARGET (1 && ENABLE_1_42_0)
// Add Geometry::Transformation class and use it into ModelInstance, ModelVolume and GLVolume
#define ENABLE_MODELVOLUME_TRANSFORM (1 && ENABLE_1_42_0)
#endif // _technologies_h_ #endif // _technologies_h_

View file

@ -151,12 +151,14 @@ void Bed_2D::repaint()
} }
// convert G - code coordinates into pixels // convert G - code coordinates into pixels
Point Bed_2D::to_pixels(Vec2d point){ Point Bed_2D::to_pixels(Vec2d point)
{
auto p = point * m_scale_factor + m_shift; auto p = point * m_scale_factor + m_shift;
return Point(p(0), GetSize().GetHeight() - p(1)); return Point(p(0), GetSize().GetHeight() - p(1));
} }
void Bed_2D::mouse_event(wxMouseEvent event){ void Bed_2D::mouse_event(wxMouseEvent event)
{
if (!m_interactive) return; if (!m_interactive) return;
if (!m_painted) return; if (!m_painted) return;
@ -170,11 +172,13 @@ void Bed_2D::mouse_event(wxMouseEvent event){
} }
// convert pixels into G - code coordinates // convert pixels into G - code coordinates
Vec2d Bed_2D::to_units(Point point){ Vec2d Bed_2D::to_units(Point point)
{
return (Vec2d(point(0), GetSize().GetHeight() - point(1)) - m_shift) * (1. / m_scale_factor); return (Vec2d(point(0), GetSize().GetHeight() - point(1)) - m_shift) * (1. / m_scale_factor);
} }
void Bed_2D::set_pos(Vec2d pos){ void Bed_2D::set_pos(Vec2d pos)
{
m_pos = pos; m_pos = pos;
Refresh(); Refresh();
} }

View file

@ -195,6 +195,9 @@ const float GLVolume::OUTSIDE_COLOR[4] = { 0.0f, 0.38f, 0.8f, 1.0f };
const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f }; const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f };
GLVolume::GLVolume(float r, float g, float b, float a) GLVolume::GLVolume(float r, float g, float b, float a)
#if ENABLE_MODELVOLUME_TRANSFORM
: m_transformed_bounding_box_dirty(true)
#else
: m_offset(Vec3d::Zero()) : m_offset(Vec3d::Zero())
, m_rotation(Vec3d::Zero()) , m_rotation(Vec3d::Zero())
, m_scaling_factor(Vec3d::Ones()) , m_scaling_factor(Vec3d::Ones())
@ -204,6 +207,7 @@ GLVolume::GLVolume(float r, float g, float b, float a)
, m_world_matrix(Transform3f::Identity()) , m_world_matrix(Transform3f::Identity())
, m_world_matrix_dirty(true) , m_world_matrix_dirty(true)
, m_transformed_bounding_box_dirty(true) , m_transformed_bounding_box_dirty(true)
#endif // ENABLE_MODELVOLUME_TRANSFORM
, m_transformed_convex_hull_bounding_box_dirty(true) , m_transformed_convex_hull_bounding_box_dirty(true)
, m_convex_hull(nullptr) , m_convex_hull(nullptr)
, composite_id(-1) , composite_id(-1)
@ -260,6 +264,7 @@ void GLVolume::set_render_color()
set_render_color(color, 4); set_render_color(color, 4);
} }
#if !ENABLE_MODELVOLUME_TRANSFORM
const Vec3d& GLVolume::get_rotation() const const Vec3d& GLVolume::get_rotation() const
{ {
return m_rotation; return m_rotation;
@ -360,6 +365,7 @@ void GLVolume::set_mirror(Axis axis, double mirror)
} }
} }
#endif // ENABLE_MIRROR #endif // ENABLE_MIRROR
#endif // !ENABLE_MODELVOLUME_TRANSFORM
void GLVolume::set_convex_hull(const TriangleMesh& convex_hull) void GLVolume::set_convex_hull(const TriangleMesh& convex_hull)
{ {
@ -386,6 +392,7 @@ void GLVolume::set_drag_group_id(const std::string& drag_by)
} }
#endif // !ENABLE_EXTENDED_SELECTION #endif // !ENABLE_EXTENDED_SELECTION
#if !ENABLE_MODELVOLUME_TRANSFORM
const Transform3f& GLVolume::world_matrix() const const Transform3f& GLVolume::world_matrix() const
{ {
if (m_world_matrix_dirty) if (m_world_matrix_dirty)
@ -399,12 +406,17 @@ const Transform3f& GLVolume::world_matrix() const
} }
return m_world_matrix; return m_world_matrix;
} }
#endif // !ENABLE_MODELVOLUME_TRANSFORM
const BoundingBoxf3& GLVolume::transformed_bounding_box() const const BoundingBoxf3& GLVolume::transformed_bounding_box() const
{ {
if (m_transformed_bounding_box_dirty) if (m_transformed_bounding_box_dirty)
{ {
#if ENABLE_MODELVOLUME_TRANSFORM
m_transformed_bounding_box = bounding_box.transformed(world_matrix());
#else
m_transformed_bounding_box = bounding_box.transformed(world_matrix().cast<double>()); m_transformed_bounding_box = bounding_box.transformed(world_matrix().cast<double>());
#endif // ENABLE_MODELVOLUME_TRANSFORM
m_transformed_bounding_box_dirty = false; m_transformed_bounding_box_dirty = false;
} }
@ -415,10 +427,17 @@ const BoundingBoxf3& GLVolume::transformed_convex_hull_bounding_box() const
{ {
if (m_transformed_convex_hull_bounding_box_dirty) if (m_transformed_convex_hull_bounding_box_dirty)
{ {
#if ENABLE_MODELVOLUME_TRANSFORM
if ((m_convex_hull != nullptr) && (m_convex_hull->stl.stats.number_of_facets > 0))
m_transformed_convex_hull_bounding_box = m_convex_hull->transformed_bounding_box(world_matrix());
else
m_transformed_convex_hull_bounding_box = bounding_box.transformed(world_matrix());
#else
if ((m_convex_hull != nullptr) && (m_convex_hull->stl.stats.number_of_facets > 0)) if ((m_convex_hull != nullptr) && (m_convex_hull->stl.stats.number_of_facets > 0))
m_transformed_convex_hull_bounding_box = m_convex_hull->transformed_bounding_box(world_matrix().cast<double>()); m_transformed_convex_hull_bounding_box = m_convex_hull->transformed_bounding_box(world_matrix().cast<double>());
else else
m_transformed_convex_hull_bounding_box = bounding_box.transformed(world_matrix().cast<double>()); m_transformed_convex_hull_bounding_box = bounding_box.transformed(world_matrix().cast<double>());
#endif // ENABLE_MODELVOLUME_TRANSFORM
m_transformed_convex_hull_bounding_box_dirty = false; m_transformed_convex_hull_bounding_box_dirty = false;
} }
@ -469,7 +488,11 @@ void GLVolume::render() const
::glCullFace(GL_BACK); ::glCullFace(GL_BACK);
::glPushMatrix(); ::glPushMatrix();
#if ENABLE_MODELVOLUME_TRANSFORM
::glMultMatrixd(world_matrix().data());
#else
::glMultMatrixf(world_matrix().data()); ::glMultMatrixf(world_matrix().data());
#endif // ENABLE_MODELVOLUME_TRANSFORM
if (this->indexed_vertex_array.indexed()) if (this->indexed_vertex_array.indexed())
this->indexed_vertex_array.render(this->tverts_range, this->qverts_range); this->indexed_vertex_array.render(this->tverts_range, this->qverts_range);
else else
@ -507,7 +530,11 @@ void GLVolume::render_using_layer_height() const
glUniform1f(z_cursor_band_width_id, (GLfloat)layer_height_texture_data.edit_band_width); glUniform1f(z_cursor_band_width_id, (GLfloat)layer_height_texture_data.edit_band_width);
if (world_matrix_id >= 0) if (world_matrix_id >= 0)
#if ENABLE_MODELVOLUME_TRANSFORM
::glUniformMatrix4fv(world_matrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast<float>().data());
#else
::glUniformMatrix4fv(world_matrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data()); ::glUniformMatrix4fv(world_matrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data());
#endif // ENABLE_MODELVOLUME_TRANSFORM
GLsizei w = (GLsizei)layer_height_texture_width(); GLsizei w = (GLsizei)layer_height_texture_width();
GLsizei h = (GLsizei)layer_height_texture_height(); GLsizei h = (GLsizei)layer_height_texture_height();
@ -567,7 +594,11 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0);
if (worldmatrix_id != -1) if (worldmatrix_id != -1)
#if ENABLE_MODELVOLUME_TRANSFORM
::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast<float>().data());
#else
::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data()); ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data());
#endif // ENABLE_MODELVOLUME_TRANSFORM
render(); render();
@ -586,7 +617,11 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0);
if (worldmatrix_id != -1) if (worldmatrix_id != -1)
#if ENABLE_MODELVOLUME_TRANSFORM
::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().cast<float>().data());
#else
::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data()); ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data());
#endif // ENABLE_MODELVOLUME_TRANSFORM
::glBindBuffer(GL_ARRAY_BUFFER, indexed_vertex_array.vertices_and_normals_interleaved_VBO_id); ::glBindBuffer(GL_ARRAY_BUFFER, indexed_vertex_array.vertices_and_normals_interleaved_VBO_id);
::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))); ::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)));
@ -594,7 +629,11 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
::glPushMatrix(); ::glPushMatrix();
#if ENABLE_MODELVOLUME_TRANSFORM
::glMultMatrixd(world_matrix().data());
#else
::glMultMatrixf(world_matrix().data()); ::glMultMatrixf(world_matrix().data());
#endif // ENABLE_MODELVOLUME_TRANSFORM
if (n_triangles > 0) if (n_triangles > 0)
{ {
@ -638,7 +677,11 @@ void GLVolume::render_legacy() const
::glPushMatrix(); ::glPushMatrix();
#if ENABLE_MODELVOLUME_TRANSFORM
::glMultMatrixd(world_matrix().data());
#else
::glMultMatrixf(world_matrix().data()); ::glMultMatrixf(world_matrix().data());
#endif // ENABLE_MODELVOLUME_TRANSFORM
if (n_triangles > 0) if (n_triangles > 0)
::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, indexed_vertex_array.triangle_indices.data() + tverts_range.first); ::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, indexed_vertex_array.triangle_indices.data() + tverts_range.first);
@ -767,12 +810,16 @@ std::vector<int> GLVolumeCollection::load_object(
} }
v.is_modifier = ! model_volume->is_model_part(); v.is_modifier = ! model_volume->is_model_part();
v.shader_outside_printer_detection_enabled = model_volume->is_model_part(); v.shader_outside_printer_detection_enabled = model_volume->is_model_part();
#if ENABLE_MODELVOLUME_TRANSFORM
v.set_transformation(instance->get_transformation());
#else
v.set_offset(instance->get_offset()); v.set_offset(instance->get_offset());
v.set_rotation(instance->get_rotation()); v.set_rotation(instance->get_rotation());
v.set_scaling_factor(instance->get_scaling_factor()); v.set_scaling_factor(instance->get_scaling_factor());
#if ENABLE_MIRROR #if ENABLE_MIRROR
v.set_mirror(instance->get_mirror()); v.set_mirror(instance->get_mirror());
#endif // ENABLE_MIRROR #endif // ENABLE_MIRROR
#endif // ENABLE_MODELVOLUME_TRANSFORM
} }
} }

View file

@ -254,6 +254,9 @@ public:
GLVolume(const float *rgba) : GLVolume(rgba[0], rgba[1], rgba[2], rgba[3]) {} GLVolume(const float *rgba) : GLVolume(rgba[0], rgba[1], rgba[2], rgba[3]) {}
private: private:
#if ENABLE_MODELVOLUME_TRANSFORM
Geometry::Transformation m_transformation;
#else
// Offset of the volume to be rendered. // Offset of the volume to be rendered.
Vec3d m_offset; Vec3d m_offset;
// Rotation around three axes of the volume to be rendered. // Rotation around three axes of the volume to be rendered.
@ -268,6 +271,7 @@ private:
mutable Transform3f m_world_matrix; mutable Transform3f m_world_matrix;
// Whether or not is needed to recalculate the world matrix. // Whether or not is needed to recalculate the world matrix.
mutable bool m_world_matrix_dirty; mutable bool m_world_matrix_dirty;
#endif // ENABLE_MODELVOLUME_TRANSFORM
// Bounding box of this volume, in unscaled coordinates. // Bounding box of this volume, in unscaled coordinates.
mutable BoundingBoxf3 m_transformed_bounding_box; mutable BoundingBoxf3 m_transformed_bounding_box;
// Whether or not is needed to recalculate the transformed bounding box. // Whether or not is needed to recalculate the transformed bounding box.
@ -280,7 +284,6 @@ private:
mutable bool m_transformed_convex_hull_bounding_box_dirty; mutable bool m_transformed_convex_hull_bounding_box_dirty;
public: public:
// Bounding box of this volume, in unscaled coordinates. // Bounding box of this volume, in unscaled coordinates.
BoundingBoxf3 bounding_box; BoundingBoxf3 bounding_box;
// Color of the triangles / quads held by this volume. // Color of the triangles / quads held by this volume.
@ -333,6 +336,36 @@ public:
// Sets render color in dependence of current state // Sets render color in dependence of current state
void set_render_color(); void set_render_color();
#if ENABLE_MODELVOLUME_TRANSFORM
const Geometry::Transformation& get_transformation() const { return m_transformation; }
void set_transformation(const Geometry::Transformation& transformation) { m_transformation = transformation; set_bounding_boxes_as_dirty(); }
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }
void set_offset(const Vec3d& offset) { m_transformation.set_offset(offset); set_bounding_boxes_as_dirty(); }
void set_offset(Axis axis, double offset) { m_transformation.set_offset(axis, offset); set_bounding_boxes_as_dirty(); }
const Vec3d& get_rotation() const { return m_transformation.get_rotation(); }
double get_rotation(Axis axis) const { return m_transformation.get_rotation(axis); }
void set_rotation(const Vec3d& rotation) { m_transformation.set_rotation(rotation); set_bounding_boxes_as_dirty(); }
void set_rotation(Axis axis, double rotation) { m_transformation.set_rotation(axis, rotation); set_bounding_boxes_as_dirty(); }
Vec3d get_scaling_factor() const { return m_transformation.get_scaling_factor(); }
double get_scaling_factor(Axis axis) const { return m_transformation.get_scaling_factor(axis); }
void set_scaling_factor(const Vec3d& scaling_factor) { m_transformation.set_scaling_factor(scaling_factor); set_bounding_boxes_as_dirty(); }
void set_scaling_factor(Axis axis, double scaling_factor) { m_transformation.set_scaling_factor(axis, scaling_factor); set_bounding_boxes_as_dirty(); }
#if ENABLE_MIRROR
const Vec3d& get_mirror() const { return m_transformation.get_mirror(); }
double get_mirror(Axis axis) const { return m_transformation.get_mirror(axis); }
void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); set_bounding_boxes_as_dirty(); }
void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); set_bounding_boxes_as_dirty(); }
#endif // ENABLE_MIRROR
#else
const Vec3d& get_rotation() const; const Vec3d& get_rotation() const;
void set_rotation(const Vec3d& rotation); void set_rotation(const Vec3d& rotation);
@ -350,6 +383,7 @@ public:
const Vec3d& get_offset() const; const Vec3d& get_offset() const;
void set_offset(const Vec3d& offset); void set_offset(const Vec3d& offset);
#endif // ENABLE_MODELVOLUME_TRANSFORM
void set_convex_hull(const TriangleMesh& convex_hull); void set_convex_hull(const TriangleMesh& convex_hull);
@ -362,7 +396,11 @@ public:
int volume_idx() const { return (this->composite_id / 1000) % 1000; } int volume_idx() const { return (this->composite_id / 1000) % 1000; }
int instance_idx() const { return this->composite_id % 1000; } int instance_idx() const { return this->composite_id % 1000; }
#if ENABLE_MODELVOLUME_TRANSFORM
const Transform3d& world_matrix() const { return m_transformation.world_matrix(); }
#else
const Transform3f& world_matrix() const; const Transform3f& world_matrix() const;
#endif // ENABLE_MODELVOLUME_TRANSFORM
const BoundingBoxf3& transformed_bounding_box() const; const BoundingBoxf3& transformed_bounding_box() const;
const BoundingBoxf3& transformed_convex_hull_bounding_box() const; const BoundingBoxf3& transformed_convex_hull_bounding_box() const;
@ -412,6 +450,10 @@ public:
} }
void reset_layer_height_texture_data() { layer_height_texture_data.reset(); } void reset_layer_height_texture_data() { layer_height_texture_data.reset(); }
#if ENABLE_MODELVOLUME_TRANSFORM
void set_bounding_boxes_as_dirty() { m_transformed_bounding_box_dirty = true; m_transformed_convex_hull_bounding_box_dirty = true; }
#endif // ENABLE_MODELVOLUME_TRANSFORM
}; };
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION

View file

@ -115,7 +115,8 @@ void BedShapePanel::build_panel(ConfigOptionPoints* default_pt)
// Called from the constructor. // Called from the constructor.
// Create a panel for a rectangular / circular / custom bed shape. // Create a panel for a rectangular / circular / custom bed shape.
ConfigOptionsGroupShp BedShapePanel::init_shape_options_page(wxString title){ ConfigOptionsGroupShp BedShapePanel::init_shape_options_page(wxString title)
{
auto panel = new wxPanel(m_shape_options_book); auto panel = new wxPanel(m_shape_options_book);
ConfigOptionsGroupShp optgroup; ConfigOptionsGroupShp optgroup;
@ -241,7 +242,8 @@ void BedShapePanel::update_shape()
rect_origin = boost::any_cast<Vec2d>(m_optgroups[SHAPE_RECTANGULAR]->get_value("rect_origin")); rect_origin = boost::any_cast<Vec2d>(m_optgroups[SHAPE_RECTANGULAR]->get_value("rect_origin"));
} }
catch (const std::exception & /* e */) { catch (const std::exception & /* e */) {
return;} return;
}
auto x = rect_size(0); auto x = rect_size(0);
auto y = rect_size(1); auto y = rect_size(1);

View file

@ -29,7 +29,8 @@ namespace Slic3r { namespace GUI {
} }
} }
void Field::PostInitialize(){ void Field::PostInitialize()
{
auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
m_Undo_btn = new MyButton(m_parent, wxID_ANY, "", wxDefaultPosition,wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); m_Undo_btn = new MyButton(m_parent, wxID_ANY, "", wxDefaultPosition,wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
m_Undo_to_sys_btn = new MyButton(m_parent, wxID_ANY, "", wxDefaultPosition,wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); m_Undo_to_sys_btn = new MyButton(m_parent, wxID_ANY, "", wxDefaultPosition,wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
@ -65,7 +66,8 @@ namespace Slic3r { namespace GUI {
BUILD(); BUILD();
} }
void Field::on_kill_focus(wxEvent& event) { void Field::on_kill_focus(wxEvent& event)
{
// Without this, there will be nasty focus bugs on Windows. // Without this, there will be nasty focus bugs on Windows.
// Also, docs for wxEvent::Skip() say "In general, it is recommended to skip all // Also, docs for wxEvent::Skip() say "In general, it is recommended to skip all
// non-command events to allow the default handling to take place." // non-command events to allow the default handling to take place."
@ -74,19 +76,22 @@ namespace Slic3r { namespace GUI {
if (m_on_kill_focus!=nullptr) if (m_on_kill_focus!=nullptr)
m_on_kill_focus(); m_on_kill_focus();
} }
void Field::on_change_field() void Field::on_change_field()
{ {
// std::cerr << "calling Field::_on_change \n"; std::cerr << "calling Field::_on_change \n";
if (m_on_change != nullptr && !m_disable_change_event) if (m_on_change != nullptr && !m_disable_change_event)
m_on_change(m_opt_id, get_value()); m_on_change(m_opt_id, get_value());
} }
void Field::on_back_to_initial_value(){ void Field::on_back_to_initial_value()
{
if (m_back_to_initial_value != nullptr && m_is_modified_value) if (m_back_to_initial_value != nullptr && m_is_modified_value)
m_back_to_initial_value(m_opt_id); m_back_to_initial_value(m_opt_id);
} }
void Field::on_back_to_sys_value(){ void Field::on_back_to_sys_value()
{
if (m_back_to_sys_value != nullptr && m_is_nonsys_value) if (m_back_to_sys_value != nullptr && m_is_nonsys_value)
m_back_to_sys_value(m_opt_id); m_back_to_sys_value(m_opt_id);
} }
@ -627,7 +632,8 @@ void ColourPicker::BUILD()
temp->SetToolTip(get_tooltip_text(clr_str)); temp->SetToolTip(get_tooltip_text(clr_str));
} }
boost::any& ColourPicker::get_value(){ boost::any& ColourPicker::get_value()
{
// boost::any m_value; // boost::any m_value;
auto colour = static_cast<wxColourPickerCtrl*>(window)->GetColour(); auto colour = static_cast<wxColourPickerCtrl*>(window)->GetColour();

View file

@ -1426,8 +1426,10 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation)
} }
} }
#if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance) if (m_mode == Instance)
_synchronize_unselected_instances(); _synchronize_unselected_instances();
#endif // !DISABLE_INSTANCES_SYNCH
m_bounding_box_dirty = true; m_bounding_box_dirty = true;
} }
@ -1453,8 +1455,10 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale)
} }
} }
#if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance) if (m_mode == Instance)
_synchronize_unselected_instances(); _synchronize_unselected_instances();
#endif // !DISABLE_INSTANCES_SYNCH
m_bounding_box_dirty = true; m_bounding_box_dirty = true;
} }
@ -1471,13 +1475,105 @@ void GLCanvas3D::Selection::mirror(Axis axis)
(*m_volumes)[i]->set_mirror(axis, -(*m_volumes)[i]->get_mirror(axis)); (*m_volumes)[i]->set_mirror(axis, -(*m_volumes)[i]->get_mirror(axis));
} }
#if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance) if (m_mode == Instance)
_synchronize_unselected_instances(); _synchronize_unselected_instances();
#endif // !DISABLE_INSTANCES_SYNCH
m_bounding_box_dirty = true; m_bounding_box_dirty = true;
} }
#endif // ENABLE_MIRROR #endif // ENABLE_MIRROR
void GLCanvas3D::Selection::translate(unsigned int object_idx, const Vec3d& displacement)
{
if (!m_valid)
return;
for (unsigned int i : m_list)
{
GLVolume* v = (*m_volumes)[i];
if (v->object_idx() == object_idx)
v->set_offset(v->get_offset() + displacement);
}
std::set<unsigned int> done; // prevent processing volumes twice
done.insert(m_list.begin(), m_list.end());
for (unsigned int i : m_list)
{
if (done.size() == m_volumes->size())
break;
int object_idx = (*m_volumes)[i]->object_idx();
if (object_idx >= 1000)
continue;
// Process unselected volumes of the object.
for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
{
if (done.size() == m_volumes->size())
break;
if (done.find(j) != done.end())
continue;
GLVolume* v = (*m_volumes)[j];
if (v->object_idx() != object_idx)
continue;
v->set_offset(v->get_offset() + displacement);
done.insert(j);
}
}
m_bounding_box_dirty = true;
}
void GLCanvas3D::Selection::translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement)
{
if (!m_valid)
return;
for (unsigned int i : m_list)
{
GLVolume* v = (*m_volumes)[i];
if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
v->set_offset(v->get_offset() + displacement);
}
std::set<unsigned int> done; // prevent processing volumes twice
done.insert(m_list.begin(), m_list.end());
for (unsigned int i : m_list)
{
if (done.size() == m_volumes->size())
break;
int object_idx = (*m_volumes)[i]->object_idx();
if (object_idx >= 1000)
continue;
// Process unselected volumes of the object.
for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
{
if (done.size() == m_volumes->size())
break;
if (done.find(j) != done.end())
continue;
GLVolume* v = (*m_volumes)[j];
if ((v->object_idx() != object_idx) || (v->instance_idx() != instance_idx))
continue;
v->set_offset(v->get_offset() + displacement);
done.insert(j);
}
}
m_bounding_box_dirty = true;
}
void GLCanvas3D::Selection::render(bool show_indirect_selection) const void GLCanvas3D::Selection::render(bool show_indirect_selection) const
{ {
if (is_empty()) if (is_empty())
@ -6648,10 +6744,10 @@ void GLCanvas3D::_on_move()
if (done.find(done_id) != done.end()) if (done.find(done_id) != done.end())
continue; continue;
done.insert(done_id);
if (object_idx < 1000) if (object_idx < 1000)
{ {
done.insert(done_id);
// Move instances. // Move instances.
ModelObject* model_object = m_model->objects[object_idx]; ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr) if (model_object != nullptr)
@ -6666,6 +6762,14 @@ void GLCanvas3D::_on_move()
wipe_tower_origin = v->get_offset(); wipe_tower_origin = v->get_offset();
} }
for (const std::pair<int, int>& i : done)
{
ModelObject* m = m_model->objects[i.first];
Vec3d shift(0.0, 0.0, -m->get_instance_min_z(i.second));
m_selection.translate(i.first, i.second, shift);
m->translate_instance(i.second, shift);
}
if (object_moved) if (object_moved)
post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_MOVED)); post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_MOVED));
@ -6700,10 +6804,19 @@ void GLCanvas3D::_on_rotate()
if (model_object != nullptr) if (model_object != nullptr)
{ {
model_object->instances[instance_idx]->set_rotation(v->get_rotation()); model_object->instances[instance_idx]->set_rotation(v->get_rotation());
model_object->instances[instance_idx]->set_offset(v->get_offset());
model_object->invalidate_bounding_box(); model_object->invalidate_bounding_box();
} }
} }
for (const std::pair<int, int>& i : done)
{
ModelObject* m = m_model->objects[i.first];
Vec3d shift(0.0, 0.0, -m->get_instance_min_z(i.second));
m_selection.translate(i.first, i.second, shift);
m->translate_instance(i.second, shift);
}
post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }
@ -6734,10 +6847,19 @@ void GLCanvas3D::_on_scale()
if (model_object != nullptr) if (model_object != nullptr)
{ {
model_object->instances[instance_idx]->set_scaling_factor(v->get_scaling_factor()); model_object->instances[instance_idx]->set_scaling_factor(v->get_scaling_factor());
model_object->instances[instance_idx]->set_offset(v->get_offset());
model_object->invalidate_bounding_box(); model_object->invalidate_bounding_box();
} }
} }
for (const std::pair<int, int>& i : done)
{
ModelObject* m = m_model->objects[i.first];
Vec3d shift(0.0, 0.0, -m->get_instance_min_z(i.second));
m_selection.translate(i.first, i.second, shift);
m->translate_instance(i.second, shift);
}
post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
} }

View file

@ -508,6 +508,9 @@ public:
void mirror(Axis axis); void mirror(Axis axis);
#endif // ENABLE_MIRROR #endif // ENABLE_MIRROR
void translate(unsigned int object_idx, const Vec3d& displacement);
void translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement);
void render(bool show_indirect_selection) const; void render(bool show_indirect_selection) const;
private: private:

View file

@ -926,7 +926,11 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
// gets transform from first selected volume // gets transform from first selected volume
const GLVolume* v = selection.get_volume(*idxs.begin()); const GLVolume* v = selection.get_volume(*idxs.begin());
#if ENABLE_MODELVOLUME_TRANSFORM
transform = v->world_matrix();
#else
transform = v->world_matrix().cast<double>(); transform = v->world_matrix().cast<double>();
#endif // ENABLE_MODELVOLUME_TRANSFORM
// gets angles from first selected volume // gets angles from first selected volume
angles = v->get_rotation(); angles = v->get_rotation();

View file

@ -239,22 +239,26 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
} }
} }
void show_error(wxWindow* parent, const wxString& message) { void show_error(wxWindow* parent, const wxString& message)
{
ErrorDialog msg(parent, message); ErrorDialog msg(parent, message);
msg.ShowModal(); msg.ShowModal();
} }
void show_error_id(int id, const std::string& message) { void show_error_id(int id, const std::string& message)
{
auto *parent = id != 0 ? wxWindow::FindWindowById(id) : nullptr; auto *parent = id != 0 ? wxWindow::FindWindowById(id) : nullptr;
show_error(parent, wxString::FromUTF8(message.data())); show_error(parent, wxString::FromUTF8(message.data()));
} }
void show_info(wxWindow* parent, const wxString& message, const wxString& title){ void show_info(wxWindow* parent, const wxString& message, const wxString& title)
{
wxMessageDialog msg_wingow(parent, message, title.empty() ? _(L("Notice")) : title, wxOK | wxICON_INFORMATION); wxMessageDialog msg_wingow(parent, message, title.empty() ? _(L("Notice")) : title, wxOK | wxICON_INFORMATION);
msg_wingow.ShowModal(); msg_wingow.ShowModal();
} }
void warning_catcher(wxWindow* parent, const wxString& message){ void warning_catcher(wxWindow* parent, const wxString& message)
{
if (message == "GLUquadricObjPtr | " + _(L("Attempt to free unreferenced scalar")) ) if (message == "GLUquadricObjPtr | " + _(L("Attempt to free unreferenced scalar")) )
return; return;
wxMessageDialog msg(parent, message, _(L("Warning")), wxOK | wxICON_WARNING); wxMessageDialog msg(parent, message, _(L("Warning")), wxOK | wxICON_WARNING);

View file

@ -267,7 +267,8 @@ void GUI_App::system_info()
// static method accepting a wxWindow object as first parameter // static method accepting a wxWindow object as first parameter
bool GUI_App::catch_error(std::function<void()> cb, bool GUI_App::catch_error(std::function<void()> cb,
// wxMessageDialog* message_dialog, // wxMessageDialog* message_dialog,
const std::string& err /*= ""*/){ const std::string& err /*= ""*/)
{
if (!err.empty()) { if (!err.empty()) {
if (cb) if (cb)
cb(); cb();
@ -280,14 +281,16 @@ bool GUI_App::catch_error(std::function<void()> cb,
} }
// static method accepting a wxWindow object as first parameter // static method accepting a wxWindow object as first parameter
void fatal_error(wxWindow* parent){ void fatal_error(wxWindow* parent)
{
show_error(parent, ""); show_error(parent, "");
// exit 1; // #ys_FIXME // exit 1; // #ys_FIXME
} }
// Called after the Preferences dialog is closed and the program settings are saved. // Called after the Preferences dialog is closed and the program settings are saved.
// Update the UI based on the current preferences. // Update the UI based on the current preferences.
void GUI_App::update_ui_from_settings(){ void GUI_App::update_ui_from_settings()
{
mainframe->update_ui_from_settings(); mainframe->update_ui_from_settings();
} }

View file

@ -150,7 +150,8 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt)
GetMainWindow()->SetToolTip(""); // hide tooltip GetMainWindow()->SetToolTip(""); // hide tooltip
} }
wxPoint ObjectList::get_mouse_position_in_control() { wxPoint ObjectList::get_mouse_position_in_control()
{
const wxPoint& pt = wxGetMousePosition(); const wxPoint& pt = wxGetMousePosition();
// wxWindow* win = GetMainWindow(); // wxWindow* win = GetMainWindow();
// wxPoint screen_pos = win->GetScreenPosition(); // wxPoint screen_pos = win->GetScreenPosition();
@ -159,10 +160,9 @@ wxPoint ObjectList::get_mouse_position_in_control() {
int ObjectList::get_selected_obj_idx() const int ObjectList::get_selected_obj_idx() const
{ {
if (GetSelectedItemsCount() == 1) { if (GetSelectedItemsCount() == 1)
auto item = GetSelection(); return m_objects_model->GetIdByItem(m_objects_model->GetTopParent(GetSelection()));
return m_objects_model->GetIdByItem(item);
}
return -1; return -1;
} }
@ -209,7 +209,8 @@ void ObjectList::update_extruder_in_config(const wxString& selection)
wxGetApp().plater()->update(); wxGetApp().plater()->update();
} }
void ObjectList::init_icons(){ void ObjectList::init_icons()
{
m_bmp_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG); m_bmp_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG);
m_bmp_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG); m_bmp_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
@ -686,6 +687,7 @@ void ObjectList::load_part( ModelObject* model_object,
{ {
wxWindow* parent = wxGetApp().tab_panel()->GetPage(0); wxWindow* parent = wxGetApp().tab_panel()->GetPage(0);
m_parts_changed = false;
wxArrayString input_files; wxArrayString input_files;
wxGetApp().open_model(parent, input_files); wxGetApp().open_model(parent, input_files);
for (int i = 0; i < input_files.size(); ++i) { for (int i = 0; i < input_files.size(); ++i) {
@ -706,6 +708,7 @@ void ObjectList::load_part( ModelObject* model_object,
if (model_object->origin_translation != Vec3d::Zero()) if (model_object->origin_translation != Vec3d::Zero())
{ {
object->center_around_origin(); object->center_around_origin();
object->ensure_on_bed();
delta = model_object->origin_translation - object->origin_translation; delta = model_object->origin_translation - object->origin_translation;
} }
for (auto volume : object->volumes) { for (auto volume : object->volumes) {
@ -737,6 +740,7 @@ void ObjectList::load_lambda( ModelObject* model_object,
{ {
auto dlg = new LambdaObjectDialog(GetMainWindow()); auto dlg = new LambdaObjectDialog(GetMainWindow());
if (dlg->ShowModal() == wxID_CANCEL) { if (dlg->ShowModal() == wxID_CANCEL) {
m_parts_changed = false;
return; return;
} }
@ -955,6 +959,11 @@ void ObjectList::split(const bool split_part)
m_parts_changed = true; m_parts_changed = true;
parts_changed(m_selected_object_id); parts_changed(m_selected_object_id);
#if ENABLE_EXTENDED_SELECTION
// restores selection
_3DScene::get_canvas(wxGetApp().canvas3D())->get_selection().add_object(m_selected_object_id);
#endif // ENABLE_EXTENDED_SELECTION
} }
bool ObjectList::get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume) bool ObjectList::get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume)
@ -995,9 +1004,17 @@ bool ObjectList::is_splittable_object(const bool split_part)
return splittable; return splittable;
} }
void ObjectList::part_settings_changed()
{
m_part_settings_changed = true;
wxGetApp().plater()->changed_object(get_selected_obj_idx());
m_part_settings_changed = false;
}
void ObjectList::parts_changed(int obj_idx) void ObjectList::parts_changed(int obj_idx)
{ {
wxGetApp().mainframe->m_plater->changed_object_settings(obj_idx); wxGetApp().plater()->changed_object(get_selected_obj_idx());
m_parts_changed = false;
} }
void ObjectList::part_selection_changed() void ObjectList::part_selection_changed()

View file

@ -99,6 +99,7 @@ public:
int get_selected_obj_idx() const; int get_selected_obj_idx() const;
bool is_parts_changed() const { return m_parts_changed; } bool is_parts_changed() const { return m_parts_changed; }
bool is_part_settings_changed() const { return m_part_settings_changed; } bool is_part_settings_changed() const { return m_part_settings_changed; }
void part_settings_changed();
void parts_changed(int obj_idx); void parts_changed(int obj_idx);
void part_selection_changed(); void part_selection_changed();

View file

@ -225,6 +225,9 @@ void ObjectManipulation::update_settings_list()
optgroup->label_width = 150; optgroup->label_width = 150;
optgroup->sidetext_width = 70; optgroup->sidetext_width = 70;
optgroup->m_on_change = [](const t_config_option_key& opt_id, const boost::any& value) {
wxGetApp().obj_list()->part_settings_changed(); };
for (auto& opt : cat.second) for (auto& opt : cat.second)
{ {
if (opt == "extruder") if (opt == "extruder")
@ -268,7 +271,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
{ {
if (selection.is_single_full_object()) if (selection.is_single_full_object())
{ {
if (wxGetApp().mainframe->m_plater->model().objects[selection.get_object_idx()]->instances.size() == 1) if (!wxGetApp().model_objects()->empty() && (*wxGetApp().model_objects())[selection.get_object_idx()]->instances.size() == 1)
{ {
// all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());

View file

@ -171,7 +171,8 @@ LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent,
// Called from the constructor. // Called from the constructor.
// Create a panel for a rectangular / circular / custom bed shape. // Create a panel for a rectangular / circular / custom bed shape.
ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(const wxString& title){ ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(const wxString& title)
{
if (!m_type_name.IsEmpty() && m_type_name != title) if (!m_type_name.IsEmpty() && m_type_name != title)
return nullptr; return nullptr;

View file

@ -369,14 +369,16 @@ void MainFrame::init_menubar()
} }
} }
void MainFrame::slice_to_png(){ void MainFrame::slice_to_png()
{
// m_plater->stop_background_process(); // m_plater->stop_background_process();
// m_plater->async_apply_config(); // m_plater->async_apply_config();
m_appController->print_ctl()->slice_to_png(); m_appController->print_ctl()->slice_to_png();
} }
// To perform the "Quck Slice", "Quick Slice and Save As", "Repeat last Quick Slice" and "Slice to SVG". // To perform the "Quck Slice", "Quick Slice and Save As", "Repeat last Quick Slice" and "Slice to SVG".
void MainFrame::quick_slice(const int qs){ void MainFrame::quick_slice(const int qs)
{
// my $progress_dialog; // my $progress_dialog;
wxString input_file; wxString input_file;
// eval // eval

View file

@ -537,7 +537,8 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
return ret; return ret;
} }
Field* ConfigOptionsGroup::get_fieldc(const t_config_option_key& opt_key, int opt_index){ Field* ConfigOptionsGroup::get_fieldc(const t_config_option_key& opt_key, int opt_index)
{
Field* field = get_field(opt_key); Field* field = get_field(opt_key);
if (field != nullptr) if (field != nullptr)
return field; return field;

View file

@ -132,18 +132,27 @@ ObjectInfo::ObjectInfo(wxWindow *parent) :
Add(grid_sizer, 0, wxEXPAND); Add(grid_sizer, 0, wxEXPAND);
} }
enum SlisedInfoIdx
{
siFilament_m,
siFilament_mm3,
siFilament_g,
siCost,
siTimeNormal,
siTimeSilent,
siWTNumbetOfToolchanges,
siCount
};
class SlicedInfo : public wxStaticBoxSizer class SlicedInfo : public wxStaticBoxSizer
{ {
public: public:
SlicedInfo(wxWindow *parent); SlicedInfo(wxWindow *parent);
void SetTextAndShow(SlisedInfoIdx idx, const wxString& text);
private: private:
wxStaticText *info_filament_m; std::vector<std::pair<wxStaticText*, wxStaticText*>> info_vec;
wxStaticText *info_filament_mm3;
wxStaticText *info_filament_g;
wxStaticText *info_cost;
wxStaticText *info_time_normal;
wxStaticText *info_time_silent;
}; };
SlicedInfo::SlicedInfo(wxWindow *parent) : SlicedInfo::SlicedInfo(wxWindow *parent) :
@ -155,23 +164,37 @@ SlicedInfo::SlicedInfo(wxWindow *parent) :
grid_sizer->SetFlexibleDirection(wxHORIZONTAL); grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
grid_sizer->AddGrowableCol(1, 1); grid_sizer->AddGrowableCol(1, 1);
auto init_info_label = [parent, grid_sizer](wxStaticText *&info_label, wxString text_label) { info_vec.reserve(siCount);
auto init_info_label = [this, parent, grid_sizer](wxString text_label) {
auto *text = new wxStaticText(parent, wxID_ANY, text_label); auto *text = new wxStaticText(parent, wxID_ANY, text_label);
text->SetFont(wxGetApp().small_font()); text->SetFont(wxGetApp().small_font());
info_label = new wxStaticText(parent, wxID_ANY, "N/A"); auto info_label = new wxStaticText(parent, wxID_ANY, "N/A");
info_label->SetFont(wxGetApp().small_font()); info_label->SetFont(wxGetApp().small_font());
grid_sizer->Add(text, 0); grid_sizer->Add(text, 0);
grid_sizer->Add(info_label, 0); grid_sizer->Add(info_label, 0);
info_vec.push_back(std::pair<wxStaticText*, wxStaticText*>(text, info_label));
}; };
init_info_label(info_filament_m, _(L("Used Filament (m)"))); init_info_label(_(L("Used Filament (m)")));
init_info_label(info_filament_mm3, _(L("Used Filament (mm³)"))); init_info_label(_(L("Used Filament (mm³)")));
init_info_label(info_filament_g, _(L("Used Filament (g)"))); init_info_label(_(L("Used Filament (g)")));
init_info_label(info_cost, _(L("Cost"))); init_info_label(_(L("Cost")));
init_info_label(info_time_normal, _(L("Estimated printing time (normal mode)"))); init_info_label(_(L("Estimated printing time (normal mode)")));
init_info_label(info_time_silent, _(L("Estimated printing time (silent mode)"))); init_info_label(_(L("Estimated printing time (silent mode)")));
init_info_label(_(L("Number of tool changes")));
Add(grid_sizer, 0, wxEXPAND); Add(grid_sizer, 0, wxEXPAND);
this->Show(false);
}
void SlicedInfo::SetTextAndShow(SlisedInfoIdx idx, const wxString& text)
{
const bool show = text != "N/A";
if (show)
info_vec[idx].second->SetLabelText(text);
info_vec[idx].first->Show(show);
info_vec[idx].second->Show(show);
} }
PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) :
@ -642,7 +665,43 @@ void Sidebar::show_info_sizers(const bool show)
{ {
p->object_info->Show(show); p->object_info->Show(show);
p->object_info->manifold_warning_icon->Show(show && p->show_manifold_warning_icon); // where is g_show_manifold_warning_icon updating? #ys_FIXME p->object_info->manifold_warning_icon->Show(show && p->show_manifold_warning_icon); // where is g_show_manifold_warning_icon updating? #ys_FIXME
p->sliced_info->Show(show && p->show_print_info); // where is g_show_print_info updating? #ys_FIXME // p->sliced_info->Show(show && p->show_print_info);
}
void Sidebar::show_sliced_info_sizer(const bool show)
{
p->plater->Freeze();
// p->show_print_info = show;
p->sliced_info->Show(show);
if (show) {
const PrintStatistics& ps = p->plater->print().print_statistics();
const bool is_wipe_tower = ps.total_wipe_tower_filament > 0;
wxString info_text = is_wipe_tower ?
wxString::Format("%.2f (%.2f %s + %.2f %s)", ps.total_used_filament / 1000,
(ps.total_used_filament - ps.total_wipe_tower_filament) / 1000, _(L("objects")),
ps.total_wipe_tower_filament / 1000, _(L("wipe tower"))) :
wxString::Format("%.2f", ps.total_used_filament / 1000);
p->sliced_info->SetTextAndShow(siFilament_m, info_text);
p->sliced_info->SetTextAndShow(siFilament_mm3, wxString::Format("%.2f", ps.total_extruded_volume));
p->sliced_info->SetTextAndShow(siFilament_g, wxString::Format("%.2f", ps.total_weight));
info_text = is_wipe_tower ?
wxString::Format("%.2f (%.2f %s + %.2f %s)", ps.total_cost,
(ps.total_cost - ps.total_wipe_tower_cost), _(L("objects")),
ps.total_wipe_tower_cost, _(L("wipe tower"))) :
wxString::Format("%.2f", ps.total_cost);
p->sliced_info->SetTextAndShow(siCost, info_text);
p->sliced_info->SetTextAndShow(siTimeNormal, ps.estimated_normal_print_time);
p->sliced_info->SetTextAndShow(siTimeSilent, ps.estimated_silent_print_time);
// if there is a wipe tower, insert number of toolchanges info into the array:
p->sliced_info->SetTextAndShow(siWTNumbetOfToolchanges, is_wipe_tower ? wxString::Format("%.d", p->plater->print().wipe_tower_data().number_of_toolchanges) : "N/A");
}
p->scrolled->Layout();
p->plater->Layout();
p->plater->Thaw();
} }
void Sidebar::show_buttons(const bool show) void Sidebar::show_buttons(const bool show)
@ -1160,6 +1219,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path> &input_
if (type_3mf) { if (type_3mf) {
for (ModelObject* model_object : model.objects) { for (ModelObject* model_object : model.objects) {
model_object->center_around_origin(); model_object->center_around_origin();
model_object->ensure_on_bed();
} }
} }
@ -1244,6 +1304,8 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode
} }
} }
object->ensure_on_bed();
// print.auto_assign_extruders(object); // print.auto_assign_extruders(object);
// print.add_model_object(object); // print.add_model_object(object);
} }
@ -1627,23 +1689,30 @@ void Plater::priv::split_object()
ModelObjectPtrs new_objects; ModelObjectPtrs new_objects;
current_model_object->split(&new_objects); current_model_object->split(&new_objects);
if (new_objects.size() == 1) if (new_objects.size() == 1)
{
Slic3r::GUI::warning_catcher(q, _(L("The selected object couldn't be split because it contains only one part."))); Slic3r::GUI::warning_catcher(q, _(L("The selected object couldn't be split because it contains only one part.")));
}
else else
{ {
unsigned int counter = 1; unsigned int counter = 1;
for (ModelObject* m : new_objects) for (ModelObject* m : new_objects)
{ {
m->name = current_model_object->name + "_" + std::to_string(counter++); m->name = current_model_object->name + "_" + std::to_string(counter++);
m->center_around_origin(); for (ModelInstance* i : current_model_object->instances)
{
m->add_instance(*i);
}
} }
remove(obj_idx); remove(obj_idx);
// load all model objects at once, otherwise the plate would be rearranged after each one // load all model objects at once, otherwise the plate would be rearranged after each one
// causing original positions not to be kept // causing original positions not to be kept
load_model_objects(new_objects); std::vector<size_t> idxs = load_model_objects(new_objects);
// select newly added objects
for (size_t idx : idxs)
{
get_selection().add_object((unsigned int)idx, false);
}
} }
#endif // ENABLE_EXTENDED_SELECTION #endif // ENABLE_EXTENDED_SELECTION
} }
@ -1677,7 +1746,7 @@ void Plater::priv::async_apply_config()
if (invalidated == Print::APPLY_STATUS_INVALIDATED) { if (invalidated == Print::APPLY_STATUS_INVALIDATED) {
// Some previously calculated data on the Print was invalidated. // Some previously calculated data on the Print was invalidated.
// Hide the slicing results, as the current slicing status is no more valid. // Hide the slicing results, as the current slicing status is no more valid.
this->sidebar->show_info_sizers(false); this->sidebar->show_sliced_info_sizer(false);
// Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared. // Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared.
// Otherwise they will be just refreshed. // Otherwise they will be just refreshed.
this->gcode_preview_data.reset(); this->gcode_preview_data.reset();
@ -1857,7 +1926,7 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
if (canceled) if (canceled)
this->statusbar()->set_status_text(L("Cancelled")); this->statusbar()->set_status_text(L("Cancelled"));
this->sidebar->show_info_sizers(success); this->sidebar->show_sliced_info_sizer(success);
// this updates buttons status // this updates buttons status
//$self->object_list_changed; //$self->object_list_changed;
@ -2548,7 +2617,7 @@ wxGLCanvas* Plater::canvas3D()
return p->canvas3D; return p->canvas3D;
} }
void Plater::changed_object_settings(int obj_idx) void Plater::changed_object(int obj_idx)
{ {
if (obj_idx < 0) if (obj_idx < 0)
return; return;
@ -2561,6 +2630,8 @@ void Plater::changed_object_settings(int obj_idx)
// recenter and re - align to Z = 0 // recenter and re - align to Z = 0
auto model_object = p->model.objects[obj_idx]; auto model_object = p->model.objects[obj_idx];
model_object->center_around_origin(); model_object->center_around_origin();
model_object->ensure_on_bed();
_3DScene::reload_scene(p->canvas3D, false);
} }
// update print // update print
@ -2571,7 +2642,6 @@ void Plater::changed_object_settings(int obj_idx)
auto selections = p->collect_selections(); auto selections = p->collect_selections();
_3DScene::set_objects_selections(p->canvas3D, selections); _3DScene::set_objects_selections(p->canvas3D, selections);
#endif // !ENABLE_EXTENDED_SELECTION #endif // !ENABLE_EXTENDED_SELECTION
_3DScene::reload_scene(p->canvas3D, false);
#if !ENABLE_MODIFIED_CAMERA_TARGET #if !ENABLE_MODIFIED_CAMERA_TARGET
_3DScene::zoom_to_volumes(p->canvas3D); _3DScene::zoom_to_volumes(p->canvas3D);
#endif // !ENABLE_MODIFIED_CAMERA_TARGET #endif // !ENABLE_MODIFIED_CAMERA_TARGET

View file

@ -78,6 +78,7 @@ public:
wxButton* get_wiping_dialog_button(); wxButton* get_wiping_dialog_button();
void update_objects_list_extruder_column(int extruders_count); void update_objects_list_extruder_column(int extruders_count);
void show_info_sizers(const bool show); void show_info_sizers(const bool show);
void show_sliced_info_sizer(const bool show);
void show_buttons(const bool show); void show_buttons(const bool show);
void show_button(ButtonAction but_action, bool show); void show_button(ButtonAction but_action, bool show);
void enable_buttons(bool enable); void enable_buttons(bool enable);
@ -122,7 +123,7 @@ public:
void export_amf(); void export_amf();
void export_3mf(); void export_3mf();
void reslice(); void reslice();
void changed_object_settings(int obj_idx); void changed_object(int obj_idx);
void send_gcode(); void send_gcode();
void on_extruders_change(int extruders_count); void on_extruders_change(int extruders_count);

View file

@ -598,7 +598,8 @@ void Tab::on_roll_back_value(const bool to_sys /*= true*/)
// Update the combo box label of the selected preset based on its "dirty" state, // Update the combo box label of the selected preset based on its "dirty" state,
// comparing the selected preset config with $self->{config}. // comparing the selected preset config with $self->{config}.
void Tab::update_dirty(){ void Tab::update_dirty()
{
m_presets->update_dirty_ui(m_presets_choice); m_presets->update_dirty_ui(m_presets_choice);
on_presets_changed(); on_presets_changed();
update_changed_ui(); update_changed_ui();
@ -1061,7 +1062,8 @@ void TabPrint::build()
} }
// Reload current config (aka presets->edited_preset->config) into the UI fields. // Reload current config (aka presets->edited_preset->config) into the UI fields.
void TabPrint::reload_config(){ void TabPrint::reload_config()
{
reload_compatible_printers_widget(); reload_compatible_printers_widget();
Tab::reload_config(); Tab::reload_config();
} }
@ -1427,7 +1429,8 @@ void TabFilament::build()
} }
// Reload current config (aka presets->edited_preset->config) into the UI fields. // Reload current config (aka presets->edited_preset->config) into the UI fields.
void TabFilament::reload_config(){ void TabFilament::reload_config()
{
reload_compatible_printers_widget(); reload_compatible_printers_widget();
Tab::reload_config(); Tab::reload_config();
} }
@ -1852,13 +1855,15 @@ void TabPrinter::build_sla()
optgroup->append_line(line); optgroup->append_line(line);
} }
void TabPrinter::update_serial_ports(){ void TabPrinter::update_serial_ports()
{
Field *field = get_field("serial_port"); Field *field = get_field("serial_port");
Choice *choice = static_cast<Choice *>(field); Choice *choice = static_cast<Choice *>(field);
choice->set_values(Utils::scan_serial_ports()); choice->set_values(Utils::scan_serial_ports());
} }
void TabPrinter::extruders_count_changed(size_t extruders_count){ void TabPrinter::extruders_count_changed(size_t extruders_count)
{
m_extruders_count = extruders_count; m_extruders_count = extruders_count;
m_preset_bundle->printers.get_edited_preset().set_num_extruders(extruders_count); m_preset_bundle->printers.get_edited_preset().set_num_extruders(extruders_count);
m_preset_bundle->update_multi_material_filament_presets(); m_preset_bundle->update_multi_material_filament_presets();
@ -2178,7 +2183,8 @@ void TabPrinter::update_fff()
Thaw(); Thaw();
} }
void TabPrinter::update_sla(){ ; } void TabPrinter::update_sla()
{ ; }
// Initialize the UI from the current preset // Initialize the UI from the current preset
void Tab::load_current_preset() void Tab::load_current_preset()