mirror of
https://github.com/FULU-Foundation/OrcaSlicer-bambulab.git
synced 2026-08-02 11:35:51 +00:00
Merge branch 'master' of https://github.com/Prusa3d/Slic3r
This commit is contained in:
+3595
-2359
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+6636
-4057
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+6729
-4117
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+6595
-3880
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+6686
-4105
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+6710
-4078
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+6692
-4114
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+5413
-3216
File diff suppressed because it is too large
Load Diff
@@ -1,32 +1,37 @@
|
|||||||
xs/src/slic3r/GUI/AboutDialog.cpp
|
src/slic3r/GUI/AboutDialog.cpp
|
||||||
xs/src/slic3r/GUI/BedShapeDialog.cpp
|
src/slic3r/GUI/BedShapeDialog.cpp
|
||||||
xs/src/slic3r/GUI/BedShapeDialog.hpp
|
src/slic3r/GUI/BedShapeDialog.hpp
|
||||||
xs/src/slic3r/GUI/BonjourDialog.cpp
|
src/slic3r/GUI/BonjourDialog.cpp
|
||||||
xs/src/slic3r/GUI/ButtonsDescription.cpp
|
src/slic3r/GUI/ButtonsDescription.cpp
|
||||||
xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp
|
src/slic3r/GUI/ConfigSnapshotDialog.cpp
|
||||||
xs/src/slic3r/GUI/ConfigWizard.cpp
|
src/slic3r/GUI/ConfigWizard.cpp
|
||||||
xs/src/slic3r/GUI/FirmwareDialog.cpp
|
src/slic3r/GUI/Field.cpp
|
||||||
xs/src/slic3r/GUI/GLCanvas3D.cpp
|
src/slic3r/GUI/FirmwareDialog.cpp
|
||||||
xs/src/slic3r/GUI/GUI.cpp
|
src/slic3r/GUI/GLCanvas3D.cpp
|
||||||
xs/src/slic3r/GUI/MsgDialog.cpp
|
src/slic3r/GUI/GLGizmo.cpp
|
||||||
xs/src/slic3r/GUI/Tab.cpp
|
src/slic3r/GUI/GUI.cpp
|
||||||
xs/src/slic3r/GUI/Tab.hpp
|
src/slic3r/GUI/GUI_App.cpp
|
||||||
xs/src/slic3r/GUI/Field.cpp
|
src/slic3r/GUI/GUI_ObjectList.cpp
|
||||||
xs/src/slic3r/GUI/OptionsGroup.cpp
|
src/slic3r/GUI/GUI_ObjectManipulation.cpp
|
||||||
xs/src/slic3r/GUI/Preset.cpp
|
src/slic3r/GUI/GUI_Preview.cpp
|
||||||
xs/src/slic3r/GUI/PresetBundle.cpp
|
src/slic3r/GUI/KBShortcutsDialog.cpp
|
||||||
xs/src/slic3r/GUI/PresetHints.cpp
|
src/slic3r/GUI/MainFrame.cpp
|
||||||
xs/src/slic3r/GUI/Preferences.cpp
|
src/slic3r/GUI/MsgDialog.cpp
|
||||||
xs/src/slic3r/GUI/RammingChart.cpp
|
src/slic3r/GUI/Plater.cpp
|
||||||
xs/src/slic3r/GUI/UpdateDialogs.cpp
|
src/slic3r/GUI/Preferences.cpp
|
||||||
xs/src/slic3r/GUI/WipeTowerDialog.cpp
|
src/slic3r/GUI/Preset.cpp
|
||||||
xs/src/slic3r/Utils/OctoPrint.cpp
|
src/slic3r/GUI/PresetBundle.cpp
|
||||||
xs/src/slic3r/Utils/PresetUpdater.cpp
|
src/slic3r/GUI/PresetHints.cpp
|
||||||
xs/src/libslic3r/Print.cpp
|
src/slic3r/GUI/PrintHostDialogs.cpp
|
||||||
xs/src/libslic3r/PrintConfig.cpp
|
src/slic3r/GUI/RammingChart.cpp
|
||||||
xs/src/libslic3r/GCode/PreviewData.cpp
|
src/slic3r/GUI/SysInfoDialog.cpp
|
||||||
lib/Slic3r/GUI.pm
|
src/slic3r/GUI/Tab.cpp
|
||||||
lib/Slic3r/GUI/MainFrame.pm
|
src/slic3r/GUI/Tab.hpp
|
||||||
lib/Slic3r/GUI/Plater.pm
|
src/slic3r/GUI/UpdateDialogs.cpp
|
||||||
lib/Slic3r/GUI/Plater/2D.pm
|
src/slic3r/GUI/WipeTowerDialog.cpp
|
||||||
lib/Slic3r/GUI/Plater/3DPreview.pm
|
src/slic3r/Utils/OctoPrint.cpp
|
||||||
|
src/slic3r/Utils/PresetUpdater.cpp
|
||||||
|
src/slic3r/Utils/FixModelByWin10.cpp
|
||||||
|
src/libslic3r/Print.cpp
|
||||||
|
src/libslic3r/PrintConfig.cpp
|
||||||
|
src/libslic3r/GCode/PreviewData.cpp
|
||||||
|
|||||||
Binary file not shown.
+6565
-4038
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
+4311
-4239
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -38,6 +38,7 @@ struct FillParams
|
|||||||
// in this case we don't try to make more continuous paths
|
// in this case we don't try to make more continuous paths
|
||||||
bool complete;
|
bool complete;
|
||||||
};
|
};
|
||||||
|
static_assert(std::is_trivially_copyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");
|
||||||
|
|
||||||
class Fill
|
class Fill
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1589,9 +1589,11 @@ void GCode::process_layer(
|
|||||||
auto objects_by_extruder_it = by_extruder.find(extruder_id);
|
auto objects_by_extruder_it = by_extruder.find(extruder_id);
|
||||||
if (objects_by_extruder_it == by_extruder.end())
|
if (objects_by_extruder_it == by_extruder.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// We are almost ready to print. However, we must go through all the objects twice to print the the overridden extrusions first (infill/perimeter wiping feature):
|
// We are almost ready to print. However, we must go through all the objects twice to print the the overridden extrusions first (infill/perimeter wiping feature):
|
||||||
for (int print_wipe_extrusions=const_cast<LayerTools&>(layer_tools).wiping_extrusions().is_anything_overridden(); print_wipe_extrusions>=0; --print_wipe_extrusions) {
|
bool is_anything_overridden = const_cast<LayerTools&>(layer_tools).wiping_extrusions().is_anything_overridden();
|
||||||
if (print_wipe_extrusions == 0)
|
for (int print_wipe_extrusions = is_anything_overridden; print_wipe_extrusions>=0; --print_wipe_extrusions) {
|
||||||
|
if (is_anything_overridden && print_wipe_extrusions == 0)
|
||||||
gcode+="; PURGING FINISHED\n";
|
gcode+="; PURGING FINISHED\n";
|
||||||
|
|
||||||
for (ObjectByExtruder &object_by_extruder : objects_by_extruder_it->second) {
|
for (ObjectByExtruder &object_by_extruder : objects_by_extruder_it->second) {
|
||||||
@@ -1628,7 +1630,7 @@ void GCode::process_layer(
|
|||||||
m_layer = layers[layer_id].layer();
|
m_layer = layers[layer_id].layer();
|
||||||
}
|
}
|
||||||
for (ObjectByExtruder::Island &island : object_by_extruder.islands) {
|
for (ObjectByExtruder::Island &island : object_by_extruder.islands) {
|
||||||
const auto& by_region_specific = const_cast<LayerTools&>(layer_tools).wiping_extrusions().is_anything_overridden() ? island.by_region_per_copy(copy_id, extruder_id, print_wipe_extrusions) : island.by_region;
|
const auto& by_region_specific = is_anything_overridden ? island.by_region_per_copy(copy_id, extruder_id, print_wipe_extrusions) : island.by_region;
|
||||||
|
|
||||||
if (print.config().infill_first) {
|
if (print.config().infill_first) {
|
||||||
gcode += this->extrude_infill(print, by_region_specific);
|
gcode += this->extrude_infill(print, by_region_specific);
|
||||||
|
|||||||
@@ -315,6 +315,9 @@ public:
|
|||||||
// Extruder ID is only valid for FFF. Returns -1 for SLA or if the extruder ID is not applicable (support volumes).
|
// Extruder ID is only valid for FFF. Returns -1 for SLA or if the extruder ID is not applicable (support volumes).
|
||||||
int extruder_id() const;
|
int extruder_id() const;
|
||||||
|
|
||||||
|
void set_splittable(const int val) { m_is_splittable = val; }
|
||||||
|
int is_splittable() const { return m_is_splittable; }
|
||||||
|
|
||||||
// Split this volume, append the result to the object owning this volume.
|
// Split this volume, append the result to the object owning this volume.
|
||||||
// Return the number of volumes created from this one.
|
// Return the number of volumes created from this one.
|
||||||
// This is useful to assign different materials to different volumes of an object.
|
// This is useful to assign different materials to different volumes of an object.
|
||||||
@@ -387,6 +390,12 @@ private:
|
|||||||
TriangleMesh m_convex_hull;
|
TriangleMesh m_convex_hull;
|
||||||
Geometry::Transformation m_transformation;
|
Geometry::Transformation m_transformation;
|
||||||
|
|
||||||
|
// flag to optimize the checking if the volume is splittable
|
||||||
|
// -1 -> is unknown value (before first cheking)
|
||||||
|
// 0 -> is not splittable
|
||||||
|
// 1 -> is splittable
|
||||||
|
int m_is_splittable {-1};
|
||||||
|
|
||||||
ModelVolume(ModelObject *object, const TriangleMesh &mesh) : mesh(mesh), m_type(MODEL_PART), object(object)
|
ModelVolume(ModelObject *object, const TriangleMesh &mesh) : mesh(mesh), m_type(MODEL_PART), object(object)
|
||||||
{
|
{
|
||||||
if (mesh.stl.stats.number_of_facets > 1)
|
if (mesh.stl.stats.number_of_facets > 1)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace arr {
|
|||||||
|
|
||||||
using namespace libnest2d;
|
using namespace libnest2d;
|
||||||
|
|
||||||
|
// Only for debugging. Prints the model object vertices on stdout.
|
||||||
std::string toString(const Model& model, bool holes = true) {
|
std::string toString(const Model& model, bool holes = true) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
@@ -78,6 +79,7 @@ std::string toString(const Model& model, bool holes = true) {
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debugging: Save model to svg file.
|
||||||
void toSVG(SVG& svg, const Model& model) {
|
void toSVG(SVG& svg, const Model& model) {
|
||||||
for(auto objptr : model.objects) {
|
for(auto objptr : model.objects) {
|
||||||
if(!objptr) continue;
|
if(!objptr) continue;
|
||||||
@@ -121,6 +123,10 @@ Box boundingBox(const Box& pilebb, const Box& ibb ) {
|
|||||||
return Box(minc, maxc);
|
return Box(minc, maxc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is "the" object function which is evaluated many times for each vertex
|
||||||
|
// (decimated with the accuracy parameter) of each object. Therefore it is
|
||||||
|
// upmost crucial for this function to be as efficient as it possibly can be but
|
||||||
|
// at the same time, it has to provide reasonable results.
|
||||||
std::tuple<double /*score*/, Box /*farthest point from bin center*/>
|
std::tuple<double /*score*/, Box /*farthest point from bin center*/>
|
||||||
objfunc(const PointImpl& bincenter,
|
objfunc(const PointImpl& bincenter,
|
||||||
const shapelike::Shapes<PolygonImpl>& merged_pile,
|
const shapelike::Shapes<PolygonImpl>& merged_pile,
|
||||||
@@ -253,6 +259,8 @@ objfunc(const PointImpl& bincenter,
|
|||||||
return std::make_tuple(score, fullbb);
|
return std::make_tuple(score, fullbb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill in the placer algorithm configuration with values carefully chosen for
|
||||||
|
// Slic3r.
|
||||||
template<class PConf>
|
template<class PConf>
|
||||||
void fillConfig(PConf& pcfg) {
|
void fillConfig(PConf& pcfg) {
|
||||||
|
|
||||||
@@ -274,13 +282,19 @@ void fillConfig(PConf& pcfg) {
|
|||||||
pcfg.parallel = true;
|
pcfg.parallel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type trait for an arranger class for different bin types (box, circle,
|
||||||
|
// polygon, etc...)
|
||||||
template<class TBin>
|
template<class TBin>
|
||||||
class AutoArranger {};
|
class AutoArranger {};
|
||||||
|
|
||||||
|
|
||||||
|
// A class encapsulating the libnest2d Nester class and extending it with other
|
||||||
|
// management and spatial index structures for acceleration.
|
||||||
template<class TBin>
|
template<class TBin>
|
||||||
class _ArrBase {
|
class _ArrBase {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
// Useful type shortcuts...
|
||||||
using Placer = TPacker<TBin>;
|
using Placer = TPacker<TBin>;
|
||||||
using Selector = FirstFitSelection;
|
using Selector = FirstFitSelection;
|
||||||
using Packer = Nester<Placer, Selector>;
|
using Packer = Nester<Placer, Selector>;
|
||||||
@@ -289,15 +303,15 @@ protected:
|
|||||||
using Pile = sl::Shapes<PolygonImpl>;
|
using Pile = sl::Shapes<PolygonImpl>;
|
||||||
|
|
||||||
Packer m_pck;
|
Packer m_pck;
|
||||||
PConfig m_pconf; // Placement configuration
|
PConfig m_pconf; // Placement configuration
|
||||||
double m_bin_area;
|
double m_bin_area;
|
||||||
SpatIndex m_rtree;
|
SpatIndex m_rtree; // spatial index for the normal (bigger) objects
|
||||||
SpatIndex m_smallsrtree;
|
SpatIndex m_smallsrtree; // spatial index for only the smaller items
|
||||||
double m_norm;
|
double m_norm; // A coefficient to scale distances
|
||||||
Pile m_merged_pile;
|
Pile m_merged_pile; // The already merged pile (vector of items)
|
||||||
Box m_pilebb;
|
Box m_pilebb; // The bounding box of the merged pile.
|
||||||
ItemGroup m_remaining;
|
ItemGroup m_remaining; // Remaining items (m_items at the beginning)
|
||||||
ItemGroup m_items;
|
ItemGroup m_items; // The items to be packed
|
||||||
public:
|
public:
|
||||||
|
|
||||||
_ArrBase(const TBin& bin, Distance dist,
|
_ArrBase(const TBin& bin, Distance dist,
|
||||||
@@ -308,6 +322,8 @@ public:
|
|||||||
{
|
{
|
||||||
fillConfig(m_pconf);
|
fillConfig(m_pconf);
|
||||||
|
|
||||||
|
// Set up a callback that is called just before arranging starts
|
||||||
|
// This functionality is provided by the Nester class (m_pack).
|
||||||
m_pconf.before_packing =
|
m_pconf.before_packing =
|
||||||
[this](const Pile& merged_pile, // merged pile
|
[this](const Pile& merged_pile, // merged pile
|
||||||
const ItemGroup& items, // packed items
|
const ItemGroup& items, // packed items
|
||||||
@@ -344,8 +360,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
// Arranger specialization for a Box shaped bin.
|
||||||
class AutoArranger<Box>: public _ArrBase<Box> {
|
template<> class AutoArranger<Box>: public _ArrBase<Box> {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AutoArranger(const Box& bin, Distance dist,
|
AutoArranger(const Box& bin, Distance dist,
|
||||||
@@ -354,6 +370,9 @@ public:
|
|||||||
_ArrBase<Box>(bin, dist, progressind, stopcond)
|
_ArrBase<Box>(bin, dist, progressind, stopcond)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Here we set up the actual object function that calls the common
|
||||||
|
// object function for all bin shapes than does an additional inside
|
||||||
|
// check for the arranged pile.
|
||||||
m_pconf.object_function = [this, bin] (const Item &item) {
|
m_pconf.object_function = [this, bin] (const Item &item) {
|
||||||
|
|
||||||
auto result = objfunc(bin.center(),
|
auto result = objfunc(bin.center(),
|
||||||
@@ -387,8 +406,8 @@ inline lnCircle to_lnCircle(const Circle& circ) {
|
|||||||
return lnCircle({circ.center()(0), circ.center()(1)}, circ.radius());
|
return lnCircle({circ.center()(0), circ.center()(1)}, circ.radius());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
// Arranger specialization for circle shaped bin.
|
||||||
class AutoArranger<lnCircle>: public _ArrBase<lnCircle> {
|
template<> class AutoArranger<lnCircle>: public _ArrBase<lnCircle> {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AutoArranger(const lnCircle& bin, Distance dist,
|
AutoArranger(const lnCircle& bin, Distance dist,
|
||||||
@@ -396,6 +415,7 @@ public:
|
|||||||
std::function<bool(void)> stopcond):
|
std::function<bool(void)> stopcond):
|
||||||
_ArrBase<lnCircle>(bin, dist, progressind, stopcond) {
|
_ArrBase<lnCircle>(bin, dist, progressind, stopcond) {
|
||||||
|
|
||||||
|
// As with the box, only the inside check is different.
|
||||||
m_pconf.object_function = [this, &bin] (const Item &item) {
|
m_pconf.object_function = [this, &bin] (const Item &item) {
|
||||||
|
|
||||||
auto result = objfunc(bin.center(),
|
auto result = objfunc(bin.center(),
|
||||||
@@ -431,8 +451,9 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
// Arranger specialization for a generalized polygon.
|
||||||
class AutoArranger<PolygonImpl>: public _ArrBase<PolygonImpl> {
|
// Warning: this is unfinished business. It may or may not work.
|
||||||
|
template<> class AutoArranger<PolygonImpl>: public _ArrBase<PolygonImpl> {
|
||||||
public:
|
public:
|
||||||
AutoArranger(const PolygonImpl& bin, Distance dist,
|
AutoArranger(const PolygonImpl& bin, Distance dist,
|
||||||
std::function<void(unsigned)> progressind,
|
std::function<void(unsigned)> progressind,
|
||||||
@@ -461,8 +482,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> // Specialization with no bin
|
// Specialization with no bin. In this case the arranger should just arrange
|
||||||
class AutoArranger<bool>: public _ArrBase<Box> {
|
// all objects into a minimum sized pile but it is not limited by a bin. A
|
||||||
|
// consequence is that only one pile should be created.
|
||||||
|
template<> class AutoArranger<bool>: public _ArrBase<Box> {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AutoArranger(Distance dist, std::function<void(unsigned)> progressind,
|
AutoArranger(Distance dist, std::function<void(unsigned)> progressind,
|
||||||
@@ -490,14 +513,15 @@ public:
|
|||||||
|
|
||||||
// A container which stores a pointer to the 3D object and its projected
|
// A container which stores a pointer to the 3D object and its projected
|
||||||
// 2D shape from top view.
|
// 2D shape from top view.
|
||||||
using ShapeData2D =
|
using ShapeData2D = std::vector<std::pair<Slic3r::ModelInstance*, Item>>;
|
||||||
std::vector<std::pair<Slic3r::ModelInstance*, Item>>;
|
|
||||||
|
|
||||||
ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
||||||
ShapeData2D ret;
|
ShapeData2D ret;
|
||||||
|
|
||||||
auto s = std::accumulate(model.objects.begin(), model.objects.end(), size_t(0),
|
// Count all the items on the bin (all the object's instances)
|
||||||
[](size_t s, ModelObject* o){
|
auto s = std::accumulate(model.objects.begin(), model.objects.end(),
|
||||||
|
size_t(0), [](size_t s, ModelObject* o)
|
||||||
|
{
|
||||||
return s + o->instances.size();
|
return s + o->instances.size();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -517,7 +541,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
|||||||
rmesh.rotate_x(float(finst->get_rotation()(X)));
|
rmesh.rotate_x(float(finst->get_rotation()(X)));
|
||||||
rmesh.rotate_y(float(finst->get_rotation()(Y)));
|
rmesh.rotate_y(float(finst->get_rotation()(Y)));
|
||||||
|
|
||||||
// TODO export the exact 2D projection
|
// TODO export the exact 2D projection. Cannot do it as libnest2d
|
||||||
|
// does not support concave shapes (yet).
|
||||||
auto p = rmesh.convex_hull();
|
auto p = rmesh.convex_hull();
|
||||||
|
|
||||||
p.make_clockwise();
|
p.make_clockwise();
|
||||||
@@ -549,6 +574,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply the calculated translations and rotations (currently disabled) to the
|
||||||
|
// Model object instances.
|
||||||
void applyResult(
|
void applyResult(
|
||||||
IndexedPackGroup::value_type& group,
|
IndexedPackGroup::value_type& group,
|
||||||
Coord batch_offset,
|
Coord batch_offset,
|
||||||
@@ -576,6 +603,7 @@ void applyResult(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the type of bed geometry from a simple vector of points.
|
||||||
BedShapeHint bedShape(const Polyline &bed) {
|
BedShapeHint bedShape(const Polyline &bed) {
|
||||||
BedShapeHint ret;
|
BedShapeHint ret;
|
||||||
|
|
||||||
@@ -654,11 +682,15 @@ BedShapeHint bedShape(const Polyline &bed) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool arrange(Model &model,
|
// The final client function to arrange the Model. A progress indicator and
|
||||||
coord_t min_obj_distance,
|
// a stop predicate can be also be passed to control the process.
|
||||||
const Polyline &bed,
|
bool arrange(Model &model, // The model with the geometries
|
||||||
BedShapeHint bedhint,
|
coord_t min_obj_distance, // Has to be in scaled (clipper) measure
|
||||||
bool first_bin_only,
|
const Polyline &bed, // The bed geometry.
|
||||||
|
BedShapeHint bedhint, // Hint about the bed geometry type.
|
||||||
|
bool first_bin_only, // What to do is not all items fit.
|
||||||
|
|
||||||
|
// Controlling callbacks.
|
||||||
std::function<void (unsigned)> progressind,
|
std::function<void (unsigned)> progressind,
|
||||||
std::function<bool ()> stopcondition)
|
std::function<bool ()> stopcondition)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2487,7 +2487,6 @@ void PrintConfigDef::init_sla_params()
|
|||||||
def->label = L("Generate supports");
|
def->label = L("Generate supports");
|
||||||
def->category = L("Supports");
|
def->category = L("Supports");
|
||||||
def->tooltip = L("Generate supports for the models");
|
def->tooltip = L("Generate supports for the models");
|
||||||
def->sidetext = L("");
|
|
||||||
def->cli = "";
|
def->cli = "";
|
||||||
def->default_value = new ConfigOptionBool(true);
|
def->default_value = new ConfigOptionBool(true);
|
||||||
|
|
||||||
@@ -2549,7 +2548,6 @@ void PrintConfigDef::init_sla_params()
|
|||||||
def->tooltip = L("Merging bridges or pillars into another pillars can "
|
def->tooltip = L("Merging bridges or pillars into another pillars can "
|
||||||
"increase the radius. Zero means no increase, one means "
|
"increase the radius. Zero means no increase, one means "
|
||||||
"full increase.");
|
"full increase.");
|
||||||
def->sidetext = L("");
|
|
||||||
def->cli = "";
|
def->cli = "";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
def->max = 1;
|
def->max = 1;
|
||||||
@@ -2631,14 +2629,13 @@ void PrintConfigDef::init_sla_params()
|
|||||||
def->label = L("Use pad");
|
def->label = L("Use pad");
|
||||||
def->category = L("Pad");
|
def->category = L("Pad");
|
||||||
def->tooltip = L("Add a pad underneath the supported model");
|
def->tooltip = L("Add a pad underneath the supported model");
|
||||||
def->sidetext = L("");
|
|
||||||
def->cli = "";
|
def->cli = "";
|
||||||
def->default_value = new ConfigOptionBool(true);
|
def->default_value = new ConfigOptionBool(true);
|
||||||
|
|
||||||
def = this->add("pad_wall_thickness", coFloat);
|
def = this->add("pad_wall_thickness", coFloat);
|
||||||
def->label = L("Pad wall thickness");
|
def->label = L("Pad wall thickness");
|
||||||
def->category = L("Pad");
|
def->category = L("Pad");
|
||||||
def->tooltip = L("");
|
// def->tooltip = L("");
|
||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
def->cli = "";
|
def->cli = "";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
@@ -2647,7 +2644,7 @@ void PrintConfigDef::init_sla_params()
|
|||||||
def = this->add("pad_wall_height", coFloat);
|
def = this->add("pad_wall_height", coFloat);
|
||||||
def->label = L("Pad wall height");
|
def->label = L("Pad wall height");
|
||||||
def->category = L("Pad");
|
def->category = L("Pad");
|
||||||
def->tooltip = L("");
|
// def->tooltip = L("");
|
||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
def->cli = "";
|
def->cli = "";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
@@ -2656,7 +2653,7 @@ void PrintConfigDef::init_sla_params()
|
|||||||
def = this->add("pad_max_merge_distance", coFloat);
|
def = this->add("pad_max_merge_distance", coFloat);
|
||||||
def->label = L("Max merge distance");
|
def->label = L("Max merge distance");
|
||||||
def->category = L("Pad");
|
def->category = L("Pad");
|
||||||
def->tooltip = L("");
|
// def->tooltip = L("");
|
||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
def->cli = "";
|
def->cli = "";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
@@ -2665,7 +2662,7 @@ void PrintConfigDef::init_sla_params()
|
|||||||
def = this->add("pad_edge_radius", coFloat);
|
def = this->add("pad_edge_radius", coFloat);
|
||||||
def->label = L("Pad edge radius");
|
def->label = L("Pad edge radius");
|
||||||
def->category = L("Pad");
|
def->category = L("Pad");
|
||||||
def->tooltip = L("");
|
// def->tooltip = L("");
|
||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
def->cli = "";
|
def->cli = "";
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "libslic3r.h"
|
#include "libslic3r.h"
|
||||||
namespace Slic3r
|
namespace Slic3r
|
||||||
@@ -91,6 +92,8 @@ struct SlicingParameters
|
|||||||
coordf_t object_print_z_min;
|
coordf_t object_print_z_min;
|
||||||
coordf_t object_print_z_max;
|
coordf_t object_print_z_max;
|
||||||
};
|
};
|
||||||
|
static_assert(std::is_trivially_copyable<SlicingParameters>::value, "SlicingParameters class is not POD (and it should be - see constructor).");
|
||||||
|
|
||||||
|
|
||||||
// The two slicing parameters lead to the same layering as long as the variable layer thickness is not in action.
|
// The two slicing parameters lead to the same layering as long as the variable layer thickness is not in action.
|
||||||
inline bool equal_layering(const SlicingParameters &sp1, const SlicingParameters &sp2)
|
inline bool equal_layering(const SlicingParameters &sp1, const SlicingParameters &sp2)
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ AboutDialog::AboutDialog()
|
|||||||
vsizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3);
|
vsizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3);
|
||||||
|
|
||||||
// this->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this);
|
// this->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this);
|
||||||
logo->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this);
|
// logo->Bind(wxEVT_LEFT_DOWN, &AboutDialog::onCloseDialog, this);
|
||||||
|
|
||||||
SetSizer(main_sizer);
|
SetSizer(main_sizer);
|
||||||
main_sizer->SetSizeHints(this);
|
main_sizer->SetSizeHints(this);
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
|
|||||||
|
|
||||||
bool default_variant = true; // Mark the first variant as default in the GUI
|
bool default_variant = true; // Mark the first variant as default in the GUI
|
||||||
for (const auto &variant : model.variants) {
|
for (const auto &variant : model.variants) {
|
||||||
const auto label = wxString::Format("%s %s %s %s", variant.name, _(L("mm")), _(L("nozzle")),
|
const auto label = wxString::Format("%s %s %s %s", variant.name, _(L("mm")), _(L("nozzle")),
|
||||||
(default_variant ? _(L("(default)")) : wxString()));
|
(default_variant ? "(" + _(L("default")) + ")" : wxString()));
|
||||||
default_variant = false;
|
default_variant = false;
|
||||||
auto *cbox = new Checkbox(variants_panel, label, model_id, variant.name);
|
auto *cbox = new Checkbox(variants_panel, label, model_id, variant.name);
|
||||||
const size_t idx = cboxes.size();
|
const size_t idx = cboxes.size();
|
||||||
@@ -803,7 +803,7 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||||||
// Public
|
// Public
|
||||||
|
|
||||||
ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) :
|
ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) :
|
||||||
wxDialog(parent, wxID_ANY, name(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
wxDialog(parent, wxID_ANY, _(name().ToStdString()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
||||||
p(new priv(this))
|
p(new priv(this))
|
||||||
{
|
{
|
||||||
p->run_reason = reason;
|
p->run_reason = reason;
|
||||||
@@ -899,15 +899,17 @@ bool ConfigWizard::run(PresetBundle *preset_bundle, const PresetUpdater *updater
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const wxString& ConfigWizard::name()
|
const wxString& ConfigWizard::name(const bool from_menu/* = false*/)
|
||||||
{
|
{
|
||||||
// A different naming convention is used for the Wizard on Windows vs. OSX & GTK.
|
// A different naming convention is used for the Wizard on Windows vs. OSX & GTK.
|
||||||
#if WIN32
|
#if WIN32
|
||||||
static const wxString config_wizard_name = L("Configuration Wizard");
|
static const wxString config_wizard_name = L("Configuration Wizard");
|
||||||
|
static const wxString config_wizard_name_menu = L("Configuration &Wizard");
|
||||||
#else
|
#else
|
||||||
static const wxString config_wizard_name = L("Configuration Assistant");
|
static const wxString config_wizard_name = L("Configuration Assistant");
|
||||||
|
static const wxString config_wizard_name_menu = L("Configuration &Assistant");
|
||||||
#endif
|
#endif
|
||||||
return config_wizard_name;
|
return from_menu ? config_wizard_name_menu : config_wizard_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public:
|
|||||||
// Run the Wizard. Return whether it was completed.
|
// Run the Wizard. Return whether it was completed.
|
||||||
bool run(PresetBundle *preset_bundle, const PresetUpdater *updater);
|
bool run(PresetBundle *preset_bundle, const PresetUpdater *updater);
|
||||||
|
|
||||||
static const wxString& name();
|
static const wxString& name(const bool from_menu = false);
|
||||||
private:
|
private:
|
||||||
struct priv;
|
struct priv;
|
||||||
std::unique_ptr<priv> p;
|
std::unique_ptr<priv> p;
|
||||||
|
|||||||
@@ -1049,10 +1049,6 @@ void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas
|
|||||||
|
|
||||||
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
::glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
::glBindTexture(GL_TEXTURE_2D, m_z_texture_id);
|
::glBindTexture(GL_TEXTURE_2D, m_z_texture_id);
|
||||||
::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
|
||||||
::glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, half_w, half_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
|
||||||
::glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data());
|
|
||||||
::glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data() + m_layers_texture.width * m_layers_texture.height * 4);
|
|
||||||
|
|
||||||
// Render the color bar
|
// Render the color bar
|
||||||
float l = bar_rect.get_left();
|
float l = bar_rect.get_left();
|
||||||
@@ -1061,6 +1057,7 @@ void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas
|
|||||||
float b = bar_rect.get_bottom();
|
float b = bar_rect.get_bottom();
|
||||||
|
|
||||||
::glBegin(GL_QUADS);
|
::glBegin(GL_QUADS);
|
||||||
|
::glNormal3f(0.0f, 0.0f, 1.0f);
|
||||||
::glVertex3f(l, b, 0.0f);
|
::glVertex3f(l, b, 0.0f);
|
||||||
::glVertex3f(r, b, 0.0f);
|
::glVertex3f(r, b, 0.0f);
|
||||||
::glVertex3f(r, t, m_object_max_z);
|
::glVertex3f(r, t, m_object_max_z);
|
||||||
@@ -1770,11 +1767,14 @@ void GLCanvas3D::Selection::flattening_rotate(const Vec3d& normal)
|
|||||||
|
|
||||||
for (unsigned int i : m_list)
|
for (unsigned int i : m_list)
|
||||||
{
|
{
|
||||||
Transform3d wst = m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_volume_scale_matrix();
|
Transform3d wst = m_cache.volumes_data[i].get_instance_scale_matrix();
|
||||||
Vec3d scaling_factor = Vec3d(1./wst(0,0), 1./wst(1,1), 1./wst(2,2));
|
Vec3d scaling_factor = Vec3d(1./wst(0,0), 1./wst(1,1), 1./wst(2,2));
|
||||||
|
|
||||||
Vec3d rotation = Geometry::extract_euler_angles(m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_volume_rotation_matrix());
|
Transform3d wmt = m_cache.volumes_data[i].get_instance_mirror_matrix();
|
||||||
Vec3d transformed_normal = Geometry::assemble_transform(Vec3d::Zero(), rotation, scaling_factor) * normal;
|
Vec3d mirror(wmt(0,0), wmt(1,1), wmt(2,2));
|
||||||
|
|
||||||
|
Vec3d rotation = Geometry::extract_euler_angles(m_cache.volumes_data[i].get_instance_rotation_matrix());
|
||||||
|
Vec3d transformed_normal = Geometry::assemble_transform(Vec3d::Zero(), rotation, scaling_factor, mirror) * normal;
|
||||||
transformed_normal.normalize();
|
transformed_normal.normalize();
|
||||||
|
|
||||||
Vec3d axis = transformed_normal(2) > 0.999f ? Vec3d(1., 0., 0.) : Vec3d(transformed_normal.cross(Vec3d(0., 0., -1.)));
|
Vec3d axis = transformed_normal(2) > 0.999f ? Vec3d(1., 0., 0.) : Vec3d(transformed_normal.cross(Vec3d(0., 0., -1.)));
|
||||||
|
|||||||
@@ -1526,10 +1526,9 @@ void GLGizmoFlatten::update_planes()
|
|||||||
vol_ch.transform(vol->get_matrix());
|
vol_ch.transform(vol->get_matrix());
|
||||||
ch.merge(vol_ch);
|
ch.merge(vol_ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
ch = ch.convex_hull_3d();
|
ch = ch.convex_hull_3d();
|
||||||
m_planes.clear();
|
m_planes.clear();
|
||||||
const Transform3d& inst_matrix = m_model_object->instances.front()->get_matrix();
|
const Transform3d& inst_matrix = m_model_object->instances.front()->get_matrix(true);
|
||||||
|
|
||||||
// Following constants are used for discarding too small polygons.
|
// Following constants are used for discarding too small polygons.
|
||||||
const float minimal_area = 5.f; // in square mm (world coordinates)
|
const float minimal_area = 5.f; // in square mm (world coordinates)
|
||||||
@@ -1696,10 +1695,6 @@ void GLGizmoFlatten::update_planes()
|
|||||||
|
|
||||||
// Transform back to 3D (and also back to mesh coordinates)
|
// Transform back to 3D (and also back to mesh coordinates)
|
||||||
polygon = transform(polygon, inst_matrix.inverse() * m.inverse());
|
polygon = transform(polygon, inst_matrix.inverse() * m.inverse());
|
||||||
|
|
||||||
// make sure the points are in correct order:
|
|
||||||
if ( ((inst_matrix.inverse() * m.inverse()) * Vec3d(0., 0., 1.)).dot(normal) > 0.)
|
|
||||||
std::reverse(polygon.begin(),polygon.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll sort the planes by area and only keep the 254 largest ones (because of the picking pass limitations):
|
// We'll sort the planes by area and only keep the 254 largest ones (because of the picking pass limitations):
|
||||||
@@ -1714,6 +1709,7 @@ void GLGizmoFlatten::update_planes()
|
|||||||
m_volumes_types.push_back(vol->type());
|
m_volumes_types.push_back(vol->type());
|
||||||
}
|
}
|
||||||
m_first_instance_scale = m_model_object->instances.front()->get_scaling_factor();
|
m_first_instance_scale = m_model_object->instances.front()->get_scaling_factor();
|
||||||
|
m_first_instance_mirror = m_model_object->instances.front()->get_mirror();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1726,7 +1722,8 @@ bool GLGizmoFlatten::is_plane_update_necessary() const
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// We want to recalculate when the scale changes - some planes could (dis)appear.
|
// We want to recalculate when the scale changes - some planes could (dis)appear.
|
||||||
if (! m_model_object->instances.front()->get_scaling_factor().isApprox(m_first_instance_scale))
|
if (! m_model_object->instances.front()->get_scaling_factor().isApprox(m_first_instance_scale)
|
||||||
|
|| ! m_model_object->instances.front()->get_mirror().isApprox(m_first_instance_mirror))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (unsigned int i=0; i < m_model_object->volumes.size(); ++i)
|
for (unsigned int i=0; i < m_model_object->volumes.size(); ++i)
|
||||||
|
|||||||
@@ -405,6 +405,7 @@ private:
|
|||||||
std::vector<Transform3d> m_volumes_matrices;
|
std::vector<Transform3d> m_volumes_matrices;
|
||||||
std::vector<ModelVolume::Type> m_volumes_types;
|
std::vector<ModelVolume::Type> m_volumes_types;
|
||||||
Vec3d m_first_instance_scale;
|
Vec3d m_first_instance_scale;
|
||||||
|
Vec3d m_first_instance_mirror;
|
||||||
|
|
||||||
std::vector<PlaneData> m_planes;
|
std::vector<PlaneData> m_planes;
|
||||||
mutable Vec3d m_starting_center;
|
mutable Vec3d m_starting_center;
|
||||||
|
|||||||
@@ -348,50 +348,6 @@ bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_window_size(wxTopLevelWindow *window, const std::string &name)
|
|
||||||
{
|
|
||||||
const wxSize size = window->GetSize();
|
|
||||||
const wxPoint pos = window->GetPosition();
|
|
||||||
const auto maximized = window->IsMaximized() ? "1" : "0";
|
|
||||||
|
|
||||||
get_app_config()->set((boost::format("window_%1%_size") % name).str(), (boost::format("%1%;%2%") % size.GetWidth() % size.GetHeight()).str());
|
|
||||||
get_app_config()->set((boost::format("window_%1%_maximized") % name).str(), maximized);
|
|
||||||
}
|
|
||||||
|
|
||||||
void restore_window_size(wxTopLevelWindow *window, const std::string &name)
|
|
||||||
{
|
|
||||||
// XXX: This still doesn't behave nicely in some situations (mostly on Linux).
|
|
||||||
// The problem is that it's hard to obtain window position with respect to screen geometry reliably
|
|
||||||
// from wxWidgets. Sometimes wxWidgets claim a window is located on a different screen than on which
|
|
||||||
// it's actually visible. I suspect this has something to do with window initialization (maybe we
|
|
||||||
// restore window geometry too early), but haven't yet found a workaround.
|
|
||||||
|
|
||||||
const auto display_idx = wxDisplay::GetFromWindow(window);
|
|
||||||
if (display_idx == wxNOT_FOUND) { return; }
|
|
||||||
|
|
||||||
const auto display = wxDisplay(display_idx).GetClientArea();
|
|
||||||
std::vector<std::string> pair;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const auto key_size = (boost::format("window_%1%_size") % name).str();
|
|
||||||
if (get_app_config()->has(key_size)) {
|
|
||||||
if (unescape_strings_cstyle(get_app_config()->get(key_size), pair) && pair.size() == 2) {
|
|
||||||
auto width = boost::lexical_cast<int>(pair[0]);
|
|
||||||
auto height = boost::lexical_cast<int>(pair[1]);
|
|
||||||
|
|
||||||
window->SetSize(width, height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(const boost::bad_lexical_cast &) {}
|
|
||||||
|
|
||||||
// Maximizing should be the last thing to do.
|
|
||||||
// This ensure the size and position are sane when the user un-maximizes the window.
|
|
||||||
const auto key_maximized = (boost::format("window_%1%_maximized") % name).str();
|
|
||||||
if (get_app_config()->get(key_maximized) == "1") {
|
|
||||||
window->Maximize(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void about()
|
void about()
|
||||||
{
|
{
|
||||||
AboutDialog dlg;
|
AboutDialog dlg;
|
||||||
|
|||||||
@@ -70,11 +70,6 @@ boost::filesystem::path into_path(const wxString &str);
|
|||||||
// Returns the dimensions of the screen on which the main frame is displayed
|
// Returns the dimensions of the screen on which the main frame is displayed
|
||||||
bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height);
|
bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height);
|
||||||
|
|
||||||
// Save window size and maximized status into AppConfig
|
|
||||||
void save_window_size(wxTopLevelWindow *window, const std::string &name);
|
|
||||||
// Restore the above
|
|
||||||
void restore_window_size(wxTopLevelWindow *window, const std::string &name);
|
|
||||||
|
|
||||||
// Display an About dialog
|
// Display an About dialog
|
||||||
extern void about();
|
extern void about();
|
||||||
// Ask the destop to open the datadir using the default file explorer.
|
// Ask the destop to open the datadir using the default file explorer.
|
||||||
|
|||||||
+75
-75
@@ -143,7 +143,6 @@ bool GUI_App::OnInit()
|
|||||||
init_fonts();
|
init_fonts();
|
||||||
|
|
||||||
// application frame
|
// application frame
|
||||||
std::cerr << "Creating main frame..." << std::endl;
|
|
||||||
if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr)
|
if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr)
|
||||||
wxImage::AddHandler(new wxPNGHandler());
|
wxImage::AddHandler(new wxPNGHandler());
|
||||||
mainframe = new MainFrame();
|
mainframe = new MainFrame();
|
||||||
@@ -165,27 +164,8 @@ bool GUI_App::OnInit()
|
|||||||
// to correct later layouts
|
// to correct later layouts
|
||||||
});
|
});
|
||||||
|
|
||||||
// This makes CallAfter() work
|
|
||||||
Bind(wxEVT_IDLE, [this](wxIdleEvent& event)
|
Bind(wxEVT_IDLE, [this](wxIdleEvent& event)
|
||||||
{
|
{
|
||||||
std::function<void()> cur_cb{ nullptr };
|
|
||||||
// try to get the mutex. If we can't, just skip this idle event and get the next one.
|
|
||||||
if (!callback_register.try_lock()) return;
|
|
||||||
// pop callback
|
|
||||||
if (m_cb.size() != 0) {
|
|
||||||
cur_cb = m_cb.top();
|
|
||||||
m_cb.pop();
|
|
||||||
}
|
|
||||||
// unlock mutex
|
|
||||||
this->callback_register.unlock();
|
|
||||||
|
|
||||||
try { // call the function if it's not nullptr;
|
|
||||||
if (cur_cb != nullptr) cur_cb();
|
|
||||||
}
|
|
||||||
catch (std::exception& e) {
|
|
||||||
std::cerr << "Exception thrown: " << e.what() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (app_config->dirty())
|
if (app_config->dirty())
|
||||||
app_config->save();
|
app_config->save();
|
||||||
|
|
||||||
@@ -370,6 +350,33 @@ void GUI_App::update_ui_from_settings()
|
|||||||
mainframe->update_ui_from_settings();
|
mainframe->update_ui_from_settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GUI_App::persist_window_geometry(wxTopLevelWindow *window)
|
||||||
|
{
|
||||||
|
const std::string name = into_u8(window->GetName());
|
||||||
|
|
||||||
|
window->Bind(wxEVT_CLOSE_WINDOW, [=](wxCloseEvent &event) {
|
||||||
|
window_pos_save(window, name);
|
||||||
|
event.Skip();
|
||||||
|
});
|
||||||
|
|
||||||
|
window_pos_restore(window, name);
|
||||||
|
#ifdef _WIN32
|
||||||
|
// On windows, the wxEVT_SHOW is not received if the window is created maximized
|
||||||
|
// cf. https://groups.google.com/forum/#!topic/wx-users/c7ntMt6piRI
|
||||||
|
// so we sanitize the position right away
|
||||||
|
window_pos_sanitize(window);
|
||||||
|
#else
|
||||||
|
// On other platforms on the other hand it's needed to wait before the window is actually on screen
|
||||||
|
// and some initial round of events is complete otherwise position / display index is not reported correctly.
|
||||||
|
window->Bind(wxEVT_SHOW, [=](wxShowEvent &event) {
|
||||||
|
CallAfter([=]() {
|
||||||
|
window_pos_sanitize(window);
|
||||||
|
});
|
||||||
|
event.Skip();
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void GUI_App::load_project(wxWindow *parent, wxString& input_file)
|
void GUI_App::load_project(wxWindow *parent, wxString& input_file)
|
||||||
{
|
{
|
||||||
input_file.Clear();
|
input_file.Clear();
|
||||||
@@ -394,55 +401,6 @@ void GUI_App::import_model(wxWindow *parent, wxArrayString& input_files)
|
|||||||
dialog.GetPaths(input_files);
|
dialog.GetPaths(input_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI_App::CallAfter(std::function<void()> cb)
|
|
||||||
{
|
|
||||||
// set mutex
|
|
||||||
callback_register.lock();
|
|
||||||
// push function onto stack
|
|
||||||
m_cb.emplace(cb);
|
|
||||||
// unset mutex
|
|
||||||
callback_register.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUI_App::window_pos_save(wxTopLevelWindow* window, const std::string &name)
|
|
||||||
{
|
|
||||||
if (name.empty()) { return; }
|
|
||||||
const auto config_key = (boost::format("window_%1%") % name).str();
|
|
||||||
|
|
||||||
WindowMetrics metrics = WindowMetrics::from_window(window);
|
|
||||||
app_config->set(config_key, metrics.serialize());
|
|
||||||
app_config->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUI_App::window_pos_restore(wxTopLevelWindow* window, const std::string &name)
|
|
||||||
{
|
|
||||||
if (name.empty()) { return; }
|
|
||||||
const auto config_key = (boost::format("window_%1%") % name).str();
|
|
||||||
|
|
||||||
if (! app_config->has(config_key)) { return; }
|
|
||||||
|
|
||||||
auto metrics = WindowMetrics::deserialize(app_config->get(config_key));
|
|
||||||
if (! metrics) { return; }
|
|
||||||
|
|
||||||
window->SetSize(metrics->get_rect());
|
|
||||||
window->Maximize(metrics->get_maximized());
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUI_App::window_pos_sanitize(wxTopLevelWindow* window)
|
|
||||||
{
|
|
||||||
const auto display_idx = wxDisplay::GetFromWindow(window);
|
|
||||||
if (display_idx == wxNOT_FOUND) { return; }
|
|
||||||
|
|
||||||
const auto display = wxDisplay(display_idx).GetClientArea();
|
|
||||||
|
|
||||||
auto metrics = WindowMetrics::from_window(window);
|
|
||||||
|
|
||||||
metrics.sanitize_for_display(display);
|
|
||||||
if (window->GetScreenRect() != metrics.get_rect()) {
|
|
||||||
window->SetSize(metrics.get_rect());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// select language from the list of installed languages
|
// select language from the list of installed languages
|
||||||
bool GUI_App::select_language( wxArrayString & names,
|
bool GUI_App::select_language( wxArrayString & names,
|
||||||
wxArrayLong & identifiers)
|
wxArrayLong & identifiers)
|
||||||
@@ -602,15 +560,15 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
|||||||
auto local_menu = new wxMenu();
|
auto local_menu = new wxMenu();
|
||||||
wxWindowID config_id_base = wxWindow::NewControlId((int)ConfigMenuCnt);
|
wxWindowID config_id_base = wxWindow::NewControlId((int)ConfigMenuCnt);
|
||||||
|
|
||||||
const auto config_wizard_name = _(ConfigWizard::name().wx_str());
|
const auto config_wizard_name = _(ConfigWizard::name(true).wx_str());
|
||||||
const auto config_wizard_tooltip = wxString::Format(_(L("Run %s")), config_wizard_name);
|
const auto config_wizard_tooltip = wxString::Format(_(L("Run %s")), config_wizard_name);
|
||||||
// Cmd+, is standard on OS X - what about other operating systems?
|
// Cmd+, is standard on OS X - what about other operating systems?
|
||||||
local_menu->Append(config_id_base + ConfigMenuWizard, config_wizard_name + dots, config_wizard_tooltip);
|
local_menu->Append(config_id_base + ConfigMenuWizard, config_wizard_name + dots, config_wizard_tooltip);
|
||||||
local_menu->Append(config_id_base + ConfigMenuSnapshots, _(L("Configuration Snapshots")) + dots, _(L("Inspect / activate configuration snapshots")));
|
local_menu->Append(config_id_base + ConfigMenuSnapshots, _(L("&Configuration Snapshots")) + dots, _(L("Inspect / activate configuration snapshots")));
|
||||||
local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _(L("Take Configuration Snapshot")), _(L("Capture a configuration snapshot")));
|
local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _(L("Take Configuration &Snapshot")), _(L("Capture a configuration snapshot")));
|
||||||
// local_menu->Append(config_id_base + ConfigMenuUpdate, _(L("Check for updates")), _(L("Check for configuration updates")));
|
// local_menu->Append(config_id_base + ConfigMenuUpdate, _(L("Check for updates")), _(L("Check for configuration updates")));
|
||||||
local_menu->AppendSeparator();
|
local_menu->AppendSeparator();
|
||||||
local_menu->Append(config_id_base + ConfigMenuPreferences, _(L("Preferences")) + dots + "\tCtrl+P", _(L("Application preferences")));
|
local_menu->Append(config_id_base + ConfigMenuPreferences, _(L("&Preferences")) + dots + "\tCtrl+P", _(L("Application preferences")));
|
||||||
local_menu->AppendSeparator();
|
local_menu->AppendSeparator();
|
||||||
auto mode_menu = new wxMenu();
|
auto mode_menu = new wxMenu();
|
||||||
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _(L("Simple")), _(L("Simple View Mode")));
|
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _(L("Simple")), _(L("Simple View Mode")));
|
||||||
@@ -619,9 +577,9 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
|
|||||||
mode_menu->Check(config_id_base + ConfigMenuModeSimple + get_mode(), true);
|
mode_menu->Check(config_id_base + ConfigMenuModeSimple + get_mode(), true);
|
||||||
local_menu->AppendSubMenu(mode_menu, _(L("Mode")), _(L("Slic3r View Mode")));
|
local_menu->AppendSubMenu(mode_menu, _(L("Mode")), _(L("Slic3r View Mode")));
|
||||||
local_menu->AppendSeparator();
|
local_menu->AppendSeparator();
|
||||||
local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application Language")));
|
local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application &Language")));
|
||||||
local_menu->AppendSeparator();
|
local_menu->AppendSeparator();
|
||||||
local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _(L("Flash printer firmware")), _(L("Upload a firmware image into an Arduino based printer")));
|
local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _(L("Flash printer &firmware")), _(L("Upload a firmware image into an Arduino based printer")));
|
||||||
// TODO: for when we're able to flash dictionaries
|
// TODO: for when we're able to flash dictionaries
|
||||||
// local_menu->Append(config_id_base + FirmwareMenuDict, _(L("Flash language file")), _(L("Upload a language dictionary file into a Prusa printer")));
|
// local_menu->Append(config_id_base + FirmwareMenuDict, _(L("Flash language file")), _(L("Upload a language dictionary file into a Prusa printer")));
|
||||||
|
|
||||||
@@ -789,6 +747,48 @@ wxNotebook* GUI_App::tab_panel() const
|
|||||||
return mainframe->m_tabpanel;
|
return mainframe->m_tabpanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GUI_App::window_pos_save(wxTopLevelWindow* window, const std::string &name)
|
||||||
|
{
|
||||||
|
if (name.empty()) { return; }
|
||||||
|
const auto config_key = (boost::format("window_%1%") % name).str();
|
||||||
|
|
||||||
|
WindowMetrics metrics = WindowMetrics::from_window(window);
|
||||||
|
app_config->set(config_key, metrics.serialize());
|
||||||
|
app_config->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI_App::window_pos_restore(wxTopLevelWindow* window, const std::string &name)
|
||||||
|
{
|
||||||
|
if (name.empty()) { return; }
|
||||||
|
const auto config_key = (boost::format("window_%1%") % name).str();
|
||||||
|
|
||||||
|
if (! app_config->has(config_key)) { return; }
|
||||||
|
|
||||||
|
auto metrics = WindowMetrics::deserialize(app_config->get(config_key));
|
||||||
|
if (! metrics) { return; }
|
||||||
|
|
||||||
|
window->SetSize(metrics->get_rect());
|
||||||
|
window->Maximize(metrics->get_maximized());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI_App::window_pos_sanitize(wxTopLevelWindow* window)
|
||||||
|
{
|
||||||
|
unsigned display_idx = wxDisplay::GetFromWindow(window);
|
||||||
|
wxRect display;
|
||||||
|
if (display_idx == wxNOT_FOUND) {
|
||||||
|
display = wxDisplay(0u).GetClientArea();
|
||||||
|
window->Move(display.GetTopLeft());
|
||||||
|
} else {
|
||||||
|
display = wxDisplay(display_idx).GetClientArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto metrics = WindowMetrics::from_window(window);
|
||||||
|
metrics.sanitize_for_display(display);
|
||||||
|
if (window->GetScreenRect() != metrics.get_rect()) {
|
||||||
|
window->SetSize(metrics.get_rect());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// static method accepting a wxWindow object as first parameter
|
// static method accepting a wxWindow object as first parameter
|
||||||
// void warning_catcher{
|
// void warning_catcher{
|
||||||
// my($self, $message_dialog) = @_;
|
// my($self, $message_dialog) = @_;
|
||||||
|
|||||||
@@ -73,11 +73,6 @@ class GUI_App : public wxApp
|
|||||||
{
|
{
|
||||||
bool app_conf_exists{ false };
|
bool app_conf_exists{ false };
|
||||||
|
|
||||||
// Lock to guard the callback stack
|
|
||||||
std::mutex callback_register;
|
|
||||||
// callbacks registered to run during idle event.
|
|
||||||
std::stack<std::function<void()>> m_cb{};
|
|
||||||
|
|
||||||
wxColour m_color_label_modified;
|
wxColour m_color_label_modified;
|
||||||
wxColour m_color_label_sys;
|
wxColour m_color_label_sys;
|
||||||
wxColour m_color_label_default;
|
wxColour m_color_label_default;
|
||||||
@@ -121,12 +116,9 @@ public:
|
|||||||
// wxMessageDialog* message_dialog,
|
// wxMessageDialog* message_dialog,
|
||||||
const std::string& err);
|
const std::string& err);
|
||||||
// void notify(/*message*/);
|
// void notify(/*message*/);
|
||||||
void update_ui_from_settings();
|
|
||||||
void CallAfter(std::function<void()> cb);
|
|
||||||
|
|
||||||
void window_pos_save(wxTopLevelWindow* window, const std::string &name);
|
void persist_window_geometry(wxTopLevelWindow *window);
|
||||||
void window_pos_restore(wxTopLevelWindow* window, const std::string &name);
|
void update_ui_from_settings();
|
||||||
void window_pos_sanitize(wxTopLevelWindow* window);
|
|
||||||
|
|
||||||
bool select_language(wxArrayString & names, wxArrayLong & identifiers);
|
bool select_language(wxArrayString & names, wxArrayLong & identifiers);
|
||||||
bool load_language();
|
bool load_language();
|
||||||
@@ -172,6 +164,10 @@ public:
|
|||||||
|
|
||||||
PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); }
|
PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void window_pos_save(wxTopLevelWindow* window, const std::string &name);
|
||||||
|
void window_pos_restore(wxTopLevelWindow* window, const std::string &name);
|
||||||
|
void window_pos_sanitize(wxTopLevelWindow* window);
|
||||||
};
|
};
|
||||||
DECLARE_APP(GUI_App)
|
DECLARE_APP(GUI_App)
|
||||||
|
|
||||||
|
|||||||
@@ -1105,10 +1105,14 @@ bool ObjectList::is_splittable()
|
|||||||
if (!get_volume_by_item(item, volume) || !volume)
|
if (!get_volume_by_item(item, volume) || !volume)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (volume->is_splittable() != -1) // if is_splittable value is already known
|
||||||
|
return volume->is_splittable() == 0 ? false : true;
|
||||||
|
|
||||||
TriangleMeshPtrs meshptrs = volume->mesh.split();
|
TriangleMeshPtrs meshptrs = volume->mesh.split();
|
||||||
bool splittable = meshptrs.size() > 1;
|
bool splittable = meshptrs.size() > 1;
|
||||||
for (TriangleMesh* m : meshptrs) { delete m; }
|
for (TriangleMesh* m : meshptrs) { delete m; }
|
||||||
|
|
||||||
|
volume->set_splittable(splittable ? 1 : 0);
|
||||||
return splittable;
|
return splittable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -249,9 +249,9 @@ void ObjectManipulation::UpdateAndShow(const bool show)
|
|||||||
|
|
||||||
void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection)
|
void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection)
|
||||||
{
|
{
|
||||||
m_new_move_label_string = L("Position:");
|
m_new_move_label_string = L("Position");
|
||||||
m_new_rotate_label_string = L("Rotation:");
|
m_new_rotate_label_string = L("Rotation");
|
||||||
m_new_scale_label_string = L("Scale factors:");
|
m_new_scale_label_string = L("Scale factors");
|
||||||
if (selection.is_single_full_instance())
|
if (selection.is_single_full_instance())
|
||||||
{
|
{
|
||||||
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
|
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
|
||||||
@@ -297,8 +297,8 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
|
|||||||
m_new_rotation = Vec3d::Zero();
|
m_new_rotation = Vec3d::Zero();
|
||||||
m_new_scale = Vec3d(1.0, 1.0, 1.0);
|
m_new_scale = Vec3d(1.0, 1.0, 1.0);
|
||||||
m_new_size = box.size();
|
m_new_size = box.size();
|
||||||
m_new_rotate_label_string = L("Rotate:");
|
m_new_rotate_label_string = L("Rotate");
|
||||||
m_new_scale_label_string = L("Scale:");
|
m_new_scale_label_string = L("Scale");
|
||||||
m_new_enabled = true;
|
m_new_enabled = true;
|
||||||
}
|
}
|
||||||
else if (selection.is_single_modifier() || selection.is_single_volume())
|
else if (selection.is_single_modifier() || selection.is_single_volume())
|
||||||
@@ -318,9 +318,9 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
|
|||||||
else if (wxGetApp().obj_list()->multiple_selection())
|
else if (wxGetApp().obj_list()->multiple_selection())
|
||||||
{
|
{
|
||||||
reset_settings_value();
|
reset_settings_value();
|
||||||
m_new_move_label_string = L("Translate:");
|
m_new_move_label_string = L("Translate");
|
||||||
m_new_rotate_label_string = L("Rotate:");
|
m_new_rotate_label_string = L("Rotate");
|
||||||
m_new_scale_label_string = L("Scale:");
|
m_new_scale_label_string = L("Scale");
|
||||||
m_new_size = selection.get_bounding_box().size();
|
m_new_size = selection.get_bounding_box().size();
|
||||||
m_new_enabled = true;
|
m_new_enabled = true;
|
||||||
}
|
}
|
||||||
@@ -337,21 +337,21 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
|
|||||||
void ObjectManipulation::update_if_dirty()
|
void ObjectManipulation::update_if_dirty()
|
||||||
{
|
{
|
||||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
if (m_cache.move_label_string != _(m_new_move_label_string))
|
if (m_cache.move_label_string != _(m_new_move_label_string)+ ":")
|
||||||
{
|
{
|
||||||
m_cache.move_label_string = _(m_new_move_label_string);
|
m_cache.move_label_string = _(m_new_move_label_string)+ ":";
|
||||||
m_move_Label->SetLabel(m_cache.move_label_string);
|
m_move_Label->SetLabel(m_cache.move_label_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cache.rotate_label_string != _(m_new_rotate_label_string))
|
if (m_cache.rotate_label_string != _(m_new_rotate_label_string)+ ":")
|
||||||
{
|
{
|
||||||
m_cache.rotate_label_string = _(m_new_rotate_label_string);
|
m_cache.rotate_label_string = _(m_new_rotate_label_string)+ ":";
|
||||||
m_rotate_Label->SetLabel(m_cache.rotate_label_string);
|
m_rotate_Label->SetLabel(m_cache.rotate_label_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cache.scale_label_string != _(m_new_scale_label_string))
|
if (m_cache.scale_label_string != _(m_new_scale_label_string)+ ":")
|
||||||
{
|
{
|
||||||
m_cache.scale_label_string = _(m_new_scale_label_string);
|
m_cache.scale_label_string = _(m_new_scale_label_string)+ ":";
|
||||||
m_scale_Label->SetLabel(m_cache.scale_label_string);
|
m_scale_Label->SetLabel(m_cache.scale_label_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,19 +120,28 @@ boost::optional<WindowMetrics> WindowMetrics::deserialize(const std::string &str
|
|||||||
void WindowMetrics::sanitize_for_display(const wxRect &screen_rect)
|
void WindowMetrics::sanitize_for_display(const wxRect &screen_rect)
|
||||||
{
|
{
|
||||||
rect = rect.Intersect(screen_rect);
|
rect = rect.Intersect(screen_rect);
|
||||||
|
|
||||||
|
// Prevent the window from going too far towards the right and/or bottom edge
|
||||||
|
// It's hardcoded here that the threshold is 80% of the screen size
|
||||||
|
rect.x = std::min(rect.x, screen_rect.x + 4*screen_rect.width/5);
|
||||||
|
rect.y = std::min(rect.y, screen_rect.y + 4*screen_rect.height/5);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string WindowMetrics::serialize()
|
std::string WindowMetrics::serialize() const
|
||||||
{
|
{
|
||||||
return (boost::format("%1%; %2%; %3%; %4%; %5%")
|
return (boost::format("%1%; %2%; %3%; %4%; %5%")
|
||||||
% rect.GetX()
|
% rect.x
|
||||||
% rect.GetY()
|
% rect.y
|
||||||
% rect.GetWidth()
|
% rect.width
|
||||||
% rect.GetHeight()
|
% rect.height
|
||||||
% static_cast<int>(maximized)
|
% static_cast<int>(maximized)
|
||||||
).str();
|
).str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream &os, const WindowMetrics& metrics)
|
||||||
|
{
|
||||||
|
return os << '(' << metrics.serialize() << ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
@@ -149,9 +150,11 @@ public:
|
|||||||
bool get_maximized() const { return maximized; }
|
bool get_maximized() const { return maximized; }
|
||||||
|
|
||||||
void sanitize_for_display(const wxRect &screen_rect);
|
void sanitize_for_display(const wxRect &screen_rect);
|
||||||
std::string serialize();
|
std::string serialize() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream &os, const WindowMetrics& metrics);
|
||||||
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||||||
main_shortcuts.push_back(Shortcut(ctrl+"O" ,L("Open project STL/OBJ/AMF/3MF with config, delete bed")));
|
main_shortcuts.push_back(Shortcut(ctrl+"O" ,L("Open project STL/OBJ/AMF/3MF with config, delete bed")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"I" ,L("Import STL/OBJ/AMF/3MF without config, keep bed")));
|
main_shortcuts.push_back(Shortcut(ctrl+"I" ,L("Import STL/OBJ/AMF/3MF without config, keep bed")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"L" ,L("Load Config from .ini/amf/3mf/gcode")));
|
main_shortcuts.push_back(Shortcut(ctrl+"L" ,L("Load Config from .ini/amf/3mf/gcode")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"G" ,L("Export Gcode")));
|
main_shortcuts.push_back(Shortcut(ctrl+"G" ,L("Export G-code")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"S" ,L("Save project (3MF)")));
|
main_shortcuts.push_back(Shortcut(ctrl+"S" ,L("Save project (3MF)")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+alt+"L" ,L("Load Config from .ini/amf/3mf/gcode and merge")));
|
main_shortcuts.push_back(Shortcut(ctrl+alt+"L" ,L("Load Config from .ini/amf/3mf/gcode and merge")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"R" ,L("(Re)slice")));
|
main_shortcuts.push_back(Shortcut(ctrl+"R" ,L("(Re)slice")));
|
||||||
@@ -110,8 +110,8 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||||||
main_shortcuts.push_back(Shortcut(ctrl+"1" ,L("Select Plater Tab")));
|
main_shortcuts.push_back(Shortcut(ctrl+"1" ,L("Select Plater Tab")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+alt+"U" ,L("Quick slice and Save as")));
|
main_shortcuts.push_back(Shortcut(ctrl+alt+"U" ,L("Quick slice and Save as")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"2" ,L("Select Print Settings Tab")));
|
main_shortcuts.push_back(Shortcut(ctrl+"2" ,L("Select Print Settings Tab")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"3" ,L("Select Filament Setting Tab")));
|
main_shortcuts.push_back(Shortcut(ctrl+"3" ,L("Select Filament Settings Tab")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"4" ,L("Select Printer Setting Tab")));
|
main_shortcuts.push_back(Shortcut(ctrl+"4" ,L("Select Printer Settings Tab")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"5" ,L("Switch to 3D")));
|
main_shortcuts.push_back(Shortcut(ctrl+"5" ,L("Switch to 3D")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"6" ,L("Switch to Preview")));
|
main_shortcuts.push_back(Shortcut(ctrl+"6" ,L("Switch to Preview")));
|
||||||
main_shortcuts.push_back(Shortcut(ctrl+"P" ,L("Preferences")));
|
main_shortcuts.push_back(Shortcut(ctrl+"P" ,L("Preferences")));
|
||||||
@@ -131,7 +131,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||||||
plater_shortcuts.push_back(Shortcut("A", L("Arrange")));
|
plater_shortcuts.push_back(Shortcut("A", L("Arrange")));
|
||||||
plater_shortcuts.push_back(Shortcut(ctrl+"A", L("Select All objects")));
|
plater_shortcuts.push_back(Shortcut(ctrl+"A", L("Select All objects")));
|
||||||
plater_shortcuts.push_back(Shortcut("Del", L("Delete selected")));
|
plater_shortcuts.push_back(Shortcut("Del", L("Delete selected")));
|
||||||
plater_shortcuts.push_back(Shortcut(ctrl+"Del", L("Delete all")));
|
plater_shortcuts.push_back(Shortcut(ctrl+"Del", L("Delete All")));
|
||||||
plater_shortcuts.push_back(Shortcut("M", L("Gizmo move")));
|
plater_shortcuts.push_back(Shortcut("M", L("Gizmo move")));
|
||||||
plater_shortcuts.push_back(Shortcut("S", L("Gizmo scale")));
|
plater_shortcuts.push_back(Shortcut("S", L("Gizmo scale")));
|
||||||
plater_shortcuts.push_back(Shortcut("R", L("Gizmo rotate")));
|
plater_shortcuts.push_back(Shortcut("R", L("Gizmo rotate")));
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace Slic3r {
|
|||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
MainFrame::MainFrame() :
|
MainFrame::MainFrame() :
|
||||||
wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE),
|
wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"),
|
||||||
m_printhost_queue_dlg(new PrintHostQueueDialog(this))
|
m_printhost_queue_dlg(new PrintHostQueueDialog(this))
|
||||||
{
|
{
|
||||||
// Load the icon either from the exe, or from the ico file.
|
// Load the icon either from the exe, or from the ico file.
|
||||||
@@ -48,7 +48,7 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL
|
|||||||
// initialize status bar
|
// initialize status bar
|
||||||
m_statusbar = new ProgressStatusBar(this);
|
m_statusbar = new ProgressStatusBar(this);
|
||||||
m_statusbar->embed(this);
|
m_statusbar->embed(this);
|
||||||
m_statusbar->set_status_text(_(L("Version ")) +
|
m_statusbar->set_status_text(_(L("Version")) + " " +
|
||||||
SLIC3R_VERSION +
|
SLIC3R_VERSION +
|
||||||
_(L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases")));
|
_(L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases")));
|
||||||
|
|
||||||
@@ -80,8 +80,7 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL
|
|||||||
event.Veto();
|
event.Veto();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// save window size
|
|
||||||
wxGetApp().window_pos_save(this, "mainframe");
|
|
||||||
// Save the slic3r.ini.Usually the ini file is saved from "on idle" callback,
|
// Save the slic3r.ini.Usually the ini file is saved from "on idle" callback,
|
||||||
// but in rare cases it may not have been called yet.
|
// but in rare cases it may not have been called yet.
|
||||||
wxGetApp().app_config->save();
|
wxGetApp().app_config->save();
|
||||||
@@ -93,18 +92,9 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL
|
|||||||
event.Skip();
|
event.Skip();
|
||||||
});
|
});
|
||||||
|
|
||||||
// NB: Restoring the window position is done in a two-phase manner here,
|
wxGetApp().persist_window_geometry(this);
|
||||||
// first the saved position is restored as-is and validation is done after the window is shown
|
|
||||||
// and initial round of events is complete, because on some platforms that is the only way
|
|
||||||
// to get an accurate window position & size.
|
|
||||||
wxGetApp().window_pos_restore(this, "mainframe");
|
|
||||||
Bind(wxEVT_SHOW, [this](wxShowEvent&) {
|
|
||||||
CallAfter([this]() {
|
|
||||||
wxGetApp().window_pos_sanitize(this);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
update_ui_from_settings();
|
update_ui_from_settings(); // FIXME (?)
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainFrame::init_tabpanel()
|
void MainFrame::init_tabpanel()
|
||||||
@@ -198,6 +188,12 @@ bool MainFrame::can_export_gcode() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MainFrame::can_slice() const
|
||||||
|
{
|
||||||
|
bool bg_proc = wxGetApp().app_config->get("background_processing") == "1";
|
||||||
|
return (m_plater != nullptr) ? !m_plater->model().objects.empty() && !bg_proc : false;
|
||||||
|
}
|
||||||
|
|
||||||
bool MainFrame::can_change_view() const
|
bool MainFrame::can_change_view() const
|
||||||
{
|
{
|
||||||
int page_id = m_tabpanel->GetSelection();
|
int page_id = m_tabpanel->GetSelection();
|
||||||
@@ -228,60 +224,60 @@ void MainFrame::init_menubar()
|
|||||||
// File menu
|
// File menu
|
||||||
wxMenu* fileMenu = new wxMenu;
|
wxMenu* fileMenu = new wxMenu;
|
||||||
{
|
{
|
||||||
wxMenuItem* item_open = append_menu_item(fileMenu, wxID_ANY, _(L("Open…\tCtrl+O")), _(L("Open a project file")),
|
wxMenuItem* item_open = append_menu_item(fileMenu, wxID_ANY, _(L("&Open")) + dots + "\tCtrl+O", _(L("Open a project file")),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, "brick_add.png");
|
[this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, "brick_add.png");
|
||||||
wxMenuItem* item_save = append_menu_item(fileMenu, wxID_ANY, _(L("Save\tCtrl+S")), _(L("Save current project file")),
|
wxMenuItem* item_save = append_menu_item(fileMenu, wxID_ANY, _(L("&Save")) + "\tCtrl+S", _(L("Save current project file")),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, "disk.png");
|
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, "disk.png");
|
||||||
wxMenuItem* item_save_as = append_menu_item(fileMenu, wxID_ANY, _(L("Save as…\tCtrl+Alt+S")), _(L("Save current project file as")),
|
wxMenuItem* item_save_as = append_menu_item(fileMenu, wxID_ANY, _(L("Save &as")) + dots + "\tCtrl+Alt+S", _(L("Save current project file as")),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, "disk.png");
|
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, "disk.png");
|
||||||
|
|
||||||
fileMenu->AppendSeparator();
|
fileMenu->AppendSeparator();
|
||||||
|
|
||||||
wxMenu* import_menu = new wxMenu();
|
wxMenu* import_menu = new wxMenu();
|
||||||
wxMenuItem* item_import_model = append_menu_item(import_menu, wxID_ANY, _(L("Import STL/OBJ/AMF/3MF…\tCtrl+I")), _(L("Load a model")),
|
wxMenuItem* item_import_model = append_menu_item(import_menu, wxID_ANY, _(L("Import STL/OBJ/AM&F/3MF")) + dots + "\tCtrl+I", _(L("Load a model")),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, "brick_add.png");
|
[this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, "brick_add.png");
|
||||||
import_menu->AppendSeparator();
|
import_menu->AppendSeparator();
|
||||||
append_menu_item(import_menu, wxID_ANY, _(L("Import Config…\tCtrl+L")), _(L("Load exported configuration file")),
|
append_menu_item(import_menu, wxID_ANY, _(L("Import &Config")) + dots + "\tCtrl+L", _(L("Load exported configuration file")),
|
||||||
[this](wxCommandEvent&) { load_config_file(); }, "plugin_add.png");
|
[this](wxCommandEvent&) { load_config_file(); }, "plugin_add.png");
|
||||||
append_menu_item(import_menu, wxID_ANY, _(L("Import Config from project…\tCtrl+Alt+L")), _(L("Load configuration from project file")),
|
append_menu_item(import_menu, wxID_ANY, _(L("Import Config from &project")) + dots +"\tCtrl+Alt+L", _(L("Load configuration from project file")),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->extract_config_from_project(); }, "plugin_add.png");
|
[this](wxCommandEvent&) { if (m_plater) m_plater->extract_config_from_project(); }, "plugin_add.png");
|
||||||
import_menu->AppendSeparator();
|
import_menu->AppendSeparator();
|
||||||
append_menu_item(import_menu, wxID_ANY, _(L("Import Config Bundle…")), _(L("Load presets from a bundle")),
|
append_menu_item(import_menu, wxID_ANY, _(L("Import Config &Bundle")) + dots, _(L("Load presets from a bundle")),
|
||||||
[this](wxCommandEvent&) { load_configbundle(); }, "lorry_add.png");
|
[this](wxCommandEvent&) { load_configbundle(); }, "lorry_add.png");
|
||||||
append_submenu(fileMenu, import_menu, wxID_ANY, _(L("Import")), _(L("")));
|
append_submenu(fileMenu, import_menu, wxID_ANY, _(L("&Import")), "");
|
||||||
|
|
||||||
wxMenu* export_menu = new wxMenu();
|
wxMenu* export_menu = new wxMenu();
|
||||||
wxMenuItem* item_export_gcode = append_menu_item(export_menu, wxID_ANY, _(L("Export G-code…\tCtrl+G")), _(L("Export current plate as G-code")),
|
wxMenuItem* item_export_gcode = append_menu_item(export_menu, wxID_ANY, _(L("Export &G-code")) + dots +"\tCtrl+G", _(L("Export current plate as G-code")),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(); }, "cog_go.png");
|
[this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(); }, "cog_go.png");
|
||||||
export_menu->AppendSeparator();
|
export_menu->AppendSeparator();
|
||||||
wxMenuItem* item_export_stl = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as STL…")), _(L("Export current plate as STL")),
|
wxMenuItem* item_export_stl = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &STL")) + dots, _(L("Export current plate as STL")),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, "brick_go.png");
|
[this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, "brick_go.png");
|
||||||
wxMenuItem* item_export_amf = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as AMF…")), _(L("Export current plate as AMF")),
|
wxMenuItem* item_export_amf = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &AMF")) + dots, _(L("Export current plate as AMF")),
|
||||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, "brick_go.png");
|
[this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, "brick_go.png");
|
||||||
export_menu->AppendSeparator();
|
export_menu->AppendSeparator();
|
||||||
append_menu_item(export_menu, wxID_ANY, _(L("Export Config…\tCtrl+E")), _(L("Export current configuration to file")),
|
append_menu_item(export_menu, wxID_ANY, _(L("Export &Config")) +dots +"\tCtrl+E", _(L("Export current configuration to file")),
|
||||||
[this](wxCommandEvent&) { export_config(); }, "plugin_go.png");
|
[this](wxCommandEvent&) { export_config(); }, "plugin_go.png");
|
||||||
append_menu_item(export_menu, wxID_ANY, _(L("Export Config Bundle…")), _(L("Export all presets to file")),
|
append_menu_item(export_menu, wxID_ANY, _(L("Export Config &Bundle")) + dots, _(L("Export all presets to file")),
|
||||||
[this](wxCommandEvent&) { export_configbundle(); }, "lorry_go.png");
|
[this](wxCommandEvent&) { export_configbundle(); }, "lorry_go.png");
|
||||||
append_submenu(fileMenu, export_menu, wxID_ANY, _(L("Export")), _(L("")));
|
append_submenu(fileMenu, export_menu, wxID_ANY, _(L("&Export")), "");
|
||||||
|
|
||||||
fileMenu->AppendSeparator();
|
fileMenu->AppendSeparator();
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
m_menu_item_repeat = nullptr;
|
m_menu_item_repeat = nullptr;
|
||||||
append_menu_item(fileMenu, wxID_ANY, _(L("Quick Slice…\tCtrl+U")), _(L("Slice a file into a G-code")),
|
append_menu_item(fileMenu, wxID_ANY, _(L("Quick Slice")) +dots+ "\tCtrl+U", _(L("Slice a file into a G-code")),
|
||||||
[this](wxCommandEvent&) {
|
[this](wxCommandEvent&) {
|
||||||
wxTheApp->CallAfter([this]() {
|
wxTheApp->CallAfter([this]() {
|
||||||
quick_slice();
|
quick_slice();
|
||||||
m_menu_item_repeat->Enable(is_last_input_file());
|
m_menu_item_repeat->Enable(is_last_input_file());
|
||||||
}); }, "cog_go.png");
|
}); }, "cog_go.png");
|
||||||
append_menu_item(fileMenu, wxID_ANY, _(L("Quick Slice and Save As…\tCtrl+Alt+U")), _(L("Slice a file into a G-code, save as")),
|
append_menu_item(fileMenu, wxID_ANY, _(L("Quick Slice and Save As")) +dots +"\tCtrl+Alt+U", _(L("Slice a file into a G-code, save as")),
|
||||||
[this](wxCommandEvent&) {
|
[this](wxCommandEvent&) {
|
||||||
wxTheApp->CallAfter([this]() {
|
wxTheApp->CallAfter([this]() {
|
||||||
quick_slice(qsSaveAs);
|
quick_slice(qsSaveAs);
|
||||||
m_menu_item_repeat->Enable(is_last_input_file());
|
m_menu_item_repeat->Enable(is_last_input_file());
|
||||||
}); }, "cog_go.png");
|
}); }, "cog_go.png");
|
||||||
m_menu_item_repeat = append_menu_item(fileMenu, wxID_ANY, _(L("Repeat Last Quick Slice\tCtrl+Shift+U")), _(L("Repeat last quick slice")),
|
m_menu_item_repeat = append_menu_item(fileMenu, wxID_ANY, _(L("Repeat Last Quick Slice")) +"\tCtrl+Shift+U", _(L("Repeat last quick slice")),
|
||||||
[this](wxCommandEvent&) {
|
[this](wxCommandEvent&) {
|
||||||
wxTheApp->CallAfter([this]() {
|
wxTheApp->CallAfter([this]() {
|
||||||
quick_slice(qsReslice);
|
quick_slice(qsReslice);
|
||||||
@@ -289,13 +285,13 @@ void MainFrame::init_menubar()
|
|||||||
m_menu_item_repeat->Enable(false);
|
m_menu_item_repeat->Enable(false);
|
||||||
fileMenu->AppendSeparator();
|
fileMenu->AppendSeparator();
|
||||||
#endif
|
#endif
|
||||||
m_menu_item_reslice_now = append_menu_item(fileMenu, wxID_ANY, _(L("(Re)Slice Now\tCtrl+R")), _(L("Start new slicing process")),
|
m_menu_item_reslice_now = append_menu_item(fileMenu, wxID_ANY, _(L("(Re)Slice &Now")) + "\tCtrl+R", _(L("Start new slicing process")),
|
||||||
[this](wxCommandEvent&) { reslice_now(); }, "shape_handles.png");
|
[this](wxCommandEvent&) { reslice_now(); }, "shape_handles.png");
|
||||||
fileMenu->AppendSeparator();
|
fileMenu->AppendSeparator();
|
||||||
append_menu_item(fileMenu, wxID_ANY, _(L("Repair STL file…")), _(L("Automatically repair an STL file")),
|
append_menu_item(fileMenu, wxID_ANY, _(L("&Repair STL file")) + dots, _(L("Automatically repair an STL file")),
|
||||||
[this](wxCommandEvent&) { repair_stl(); }, "wrench.png");
|
[this](wxCommandEvent&) { repair_stl(); }, "wrench.png");
|
||||||
fileMenu->AppendSeparator();
|
fileMenu->AppendSeparator();
|
||||||
append_menu_item(fileMenu, wxID_EXIT, _(L("Quit")), _(L("Quit Slic3r")),
|
append_menu_item(fileMenu, wxID_EXIT, _(L("&Quit")), _(L("Quit Slic3r")),
|
||||||
[this](wxCommandEvent&) { Close(false); });
|
[this](wxCommandEvent&) { Close(false); });
|
||||||
|
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_open->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_open->GetId());
|
||||||
@@ -305,6 +301,7 @@ void MainFrame::init_menubar()
|
|||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_gcode()); }, item_export_gcode->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_gcode()); }, item_export_gcode->GetId());
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_model()); }, item_export_stl->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_model()); }, item_export_stl->GetId());
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_model()); }, item_export_amf->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_export_model()); }, item_export_amf->GetId());
|
||||||
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_slice()); }, m_menu_item_reslice_now->GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Edit menu
|
// Edit menu
|
||||||
@@ -312,12 +309,12 @@ void MainFrame::init_menubar()
|
|||||||
if (m_plater != nullptr)
|
if (m_plater != nullptr)
|
||||||
{
|
{
|
||||||
editMenu = new wxMenu();
|
editMenu = new wxMenu();
|
||||||
wxMenuItem* item_select_all = append_menu_item(editMenu, wxID_ANY, L("Select all\tCtrl+A"), L("Selects all objects"),
|
wxMenuItem* item_select_all = append_menu_item(editMenu, wxID_ANY, _(L("&Select all")) + "\tCtrl+A", _(L("Selects all objects")),
|
||||||
[this](wxCommandEvent&) { m_plater->select_all(); }, "");
|
[this](wxCommandEvent&) { m_plater->select_all(); }, "");
|
||||||
editMenu->AppendSeparator();
|
editMenu->AppendSeparator();
|
||||||
wxMenuItem* item_delete_sel = append_menu_item(editMenu, wxID_ANY, L("Delete selected\tDel"), L("Deletes the current selection"),
|
wxMenuItem* item_delete_sel = append_menu_item(editMenu, wxID_ANY, _(L("&Delete selected")) + "\tDel", _(L("Deletes the current selection")),
|
||||||
[this](wxCommandEvent&) { m_plater->remove_selected(); }, "");
|
[this](wxCommandEvent&) { m_plater->remove_selected(); }, "");
|
||||||
wxMenuItem* item_delete_all = append_menu_item(editMenu, wxID_ANY, L("Delete all\tCtrl+Del"), L("Deletes all objects"),
|
wxMenuItem* item_delete_all = append_menu_item(editMenu, wxID_ANY, _(L("Delete &all")) + "\tCtrl+Del", _(L("Deletes all objects")),
|
||||||
[this](wxCommandEvent&) { m_plater->reset(); }, "");
|
[this](wxCommandEvent&) { m_plater->reset(); }, "");
|
||||||
|
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_select()); }, item_select_all->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_select()); }, item_select_all->GetId());
|
||||||
@@ -330,24 +327,24 @@ void MainFrame::init_menubar()
|
|||||||
{
|
{
|
||||||
size_t tab_offset = 0;
|
size_t tab_offset = 0;
|
||||||
if (m_plater) {
|
if (m_plater) {
|
||||||
append_menu_item(windowMenu, wxID_HIGHEST + 1, L("Plater Tab\tCtrl+1"), L("Show the plater"),
|
append_menu_item(windowMenu, wxID_HIGHEST + 1, _(L("&Plater Tab")) + "\tCtrl+1", _(L("Show the plater")),
|
||||||
[this](wxCommandEvent&) { select_tab(0); }, "application_view_tile.png");
|
[this](wxCommandEvent&) { select_tab(0); }, "application_view_tile.png");
|
||||||
tab_offset += 1;
|
tab_offset += 1;
|
||||||
}
|
}
|
||||||
if (tab_offset > 0) {
|
if (tab_offset > 0) {
|
||||||
windowMenu->AppendSeparator();
|
windowMenu->AppendSeparator();
|
||||||
}
|
}
|
||||||
append_menu_item(windowMenu, wxID_HIGHEST + 2, L("Print Settings Tab\tCtrl+2"), L("Show the print settings"),
|
append_menu_item(windowMenu, wxID_HIGHEST + 2, _(L("P&rint Settings Tab")) + "\tCtrl+2", _(L("Show the print settings")),
|
||||||
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 0); }, "cog.png");
|
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 0); }, "cog.png");
|
||||||
append_menu_item(windowMenu, wxID_HIGHEST + 3, L("Filament Settings Tab\tCtrl+3"), L("Show the filament settings"),
|
append_menu_item(windowMenu, wxID_HIGHEST + 3, _(L("&Filament Settings Tab")) + "\tCtrl+3", _(L("Show the filament settings")),
|
||||||
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 1); }, "spool.png");
|
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 1); }, "spool.png");
|
||||||
append_menu_item(windowMenu, wxID_HIGHEST + 4, L("Printer Settings Tab\tCtrl+4"), L("Show the printer settings"),
|
append_menu_item(windowMenu, wxID_HIGHEST + 4, _(L("Print&er Settings Tab")) + "\tCtrl+4", _(L("Show the printer settings")),
|
||||||
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 2); }, "printer_empty.png");
|
[this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 2); }, "printer_empty.png");
|
||||||
if (m_plater) {
|
if (m_plater) {
|
||||||
windowMenu->AppendSeparator();
|
windowMenu->AppendSeparator();
|
||||||
wxMenuItem* item_3d = append_menu_item(windowMenu, wxID_HIGHEST + 5, L("3D\tCtrl+5"), L("Show the 3D editing view"),
|
wxMenuItem* item_3d = append_menu_item(windowMenu, wxID_HIGHEST + 5, _(L("3&D")) + "\tCtrl+5", _(L("Show the 3D editing view")),
|
||||||
[this](wxCommandEvent&) { m_plater->select_view_3D("3D"); }, "");
|
[this](wxCommandEvent&) { m_plater->select_view_3D("3D"); }, "");
|
||||||
wxMenuItem* item_preview = append_menu_item(windowMenu, wxID_HIGHEST + 6, L("Preview\tCtrl+6"), L("Show the 3D slices preview"),
|
wxMenuItem* item_preview = append_menu_item(windowMenu, wxID_HIGHEST + 6, _(L("Pre&view")) + "\tCtrl+6", _(L("Show the 3D slices preview")),
|
||||||
[this](wxCommandEvent&) { m_plater->select_view_3D("Preview"); }, "");
|
[this](wxCommandEvent&) { m_plater->select_view_3D("Preview"); }, "");
|
||||||
|
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_3d->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_3d->GetId());
|
||||||
@@ -368,7 +365,7 @@ void MainFrame::init_menubar()
|
|||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
windowMenu->AppendSeparator();
|
windowMenu->AppendSeparator();
|
||||||
append_menu_item(windowMenu, wxID_ANY, L("Print Host Upload Queue\tCtrl+J"), L("Display the Print Host Upload Queue window"),
|
append_menu_item(windowMenu, wxID_ANY, _(L("Print &Host Upload Queue")) + "\tCtrl+J", _(L("Display the Print Host Upload Queue window")),
|
||||||
[this](wxCommandEvent&) { m_printhost_queue_dlg->Show(); }, "arrow_up.png");
|
[this](wxCommandEvent&) { m_printhost_queue_dlg->Show(); }, "arrow_up.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,14 +376,14 @@ void MainFrame::init_menubar()
|
|||||||
// \xA0 is a non-breaing space. It is entered here to spoil the automatic accelerators,
|
// \xA0 is a non-breaing space. It is entered here to spoil the automatic accelerators,
|
||||||
// as the simple numeric accelerators spoil all numeric data entry.
|
// as the simple numeric accelerators spoil all numeric data entry.
|
||||||
// The camera control accelerators are captured by GLCanvas3D::on_char().
|
// The camera control accelerators are captured by GLCanvas3D::on_char().
|
||||||
wxMenuItem* item_iso = append_menu_item(viewMenu, wxID_ANY, _(L("Iso")) + "\t\xA0" + "0", _(L("Iso View")), [this](wxCommandEvent&) { select_view("iso"); });
|
wxMenuItem* item_iso = append_menu_item(viewMenu, wxID_ANY, _(L("&Iso")) + "\t\xA0" + "0", _(L("Iso View")), [this](wxCommandEvent&) { select_view("iso"); });
|
||||||
viewMenu->AppendSeparator();
|
viewMenu->AppendSeparator();
|
||||||
wxMenuItem* item_top = append_menu_item(viewMenu, wxID_ANY, _(L("Top")) + "\t\xA0" + "1", _(L("Top View")), [this](wxCommandEvent&) { select_view("top"); });
|
wxMenuItem* item_top = append_menu_item(viewMenu, wxID_ANY, _(L("&Top")) + "\t\xA0" + "1", _(L("Top View")), [this](wxCommandEvent&) { select_view("top"); });
|
||||||
wxMenuItem* item_bottom = append_menu_item(viewMenu, wxID_ANY, _(L("Bottom")) + "\t\xA0" + "2", _(L("Bottom View")), [this](wxCommandEvent&) { select_view("bottom"); });
|
wxMenuItem* item_bottom = append_menu_item(viewMenu, wxID_ANY, _(L("&Bottom")) + "\t\xA0" + "2", _(L("Bottom View")), [this](wxCommandEvent&) { select_view("bottom"); });
|
||||||
wxMenuItem* item_front = append_menu_item(viewMenu, wxID_ANY, _(L("Front")) + "\t\xA0" + "3", _(L("Front View")), [this](wxCommandEvent&) { select_view("front"); });
|
wxMenuItem* item_front = append_menu_item(viewMenu, wxID_ANY, _(L("&Front")) + "\t\xA0" + "3", _(L("Front View")), [this](wxCommandEvent&) { select_view("front"); });
|
||||||
wxMenuItem* item_rear = append_menu_item(viewMenu, wxID_ANY, _(L("Rear")) + "\t\xA0" + "4", _(L("Rear View")), [this](wxCommandEvent&) { select_view("rear"); });
|
wxMenuItem* item_rear = append_menu_item(viewMenu, wxID_ANY, _(L("R&ear")) + "\t\xA0" + "4", _(L("Rear View")), [this](wxCommandEvent&) { select_view("rear"); });
|
||||||
wxMenuItem* item_left = append_menu_item(viewMenu, wxID_ANY, _(L("Left")) + "\t\xA0" + "5", _(L("Left View")), [this](wxCommandEvent&) { select_view("left"); });
|
wxMenuItem* item_left = append_menu_item(viewMenu, wxID_ANY, _(L("&Left")) + "\t\xA0" + "5", _(L("Left View")), [this](wxCommandEvent&) { select_view("left"); });
|
||||||
wxMenuItem* item_right = append_menu_item(viewMenu, wxID_ANY, _(L("Right")) + "\t\xA0" + "6", _(L("Right View")), [this](wxCommandEvent&) { select_view("right"); });
|
wxMenuItem* item_right = append_menu_item(viewMenu, wxID_ANY, _(L("&Right")) + "\t\xA0" + "6", _(L("Right View")), [this](wxCommandEvent&) { select_view("right"); });
|
||||||
|
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_iso->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_iso->GetId());
|
||||||
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_top->GetId());
|
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_top->GetId());
|
||||||
@@ -400,29 +397,29 @@ void MainFrame::init_menubar()
|
|||||||
// Help menu
|
// Help menu
|
||||||
auto helpMenu = new wxMenu();
|
auto helpMenu = new wxMenu();
|
||||||
{
|
{
|
||||||
append_menu_item(helpMenu, wxID_ANY, _(L("Prusa 3D Drivers")), _(L("Open the Prusa3D drivers download page in your browser")),
|
append_menu_item(helpMenu, wxID_ANY, _(L("Prusa 3D &Drivers")), _(L("Open the Prusa3D drivers download page in your browser")),
|
||||||
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://www.prusa3d.com/drivers/"); });
|
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://www.prusa3d.com/drivers/"); });
|
||||||
append_menu_item(helpMenu, wxID_ANY, _(L("Prusa Edition Releases")), _(L("Open the Prusa Edition releases page in your browser")),
|
append_menu_item(helpMenu, wxID_ANY, _(L("Prusa Edition &Releases")), _(L("Open the Prusa Edition releases page in your browser")),
|
||||||
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://github.com/prusa3d/slic3r/releases"); });
|
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://github.com/prusa3d/slic3r/releases"); });
|
||||||
//# my $versioncheck = $self->_append_menu_item($helpMenu, "Check for &Updates...", "Check for new Slic3r versions", sub{
|
//# my $versioncheck = $self->_append_menu_item($helpMenu, "Check for &Updates...", "Check for new Slic3r versions", sub{
|
||||||
//# wxTheApp->check_version(1);
|
//# wxTheApp->check_version(1);
|
||||||
//# });
|
//# });
|
||||||
//# $versioncheck->Enable(wxTheApp->have_version_check);
|
//# $versioncheck->Enable(wxTheApp->have_version_check);
|
||||||
append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r Website")), _(L("Open the Slic3r website in your browser")),
|
append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r &Website")), _(L("Open the Slic3r website in your browser")),
|
||||||
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://slic3r.org/"); });
|
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://slic3r.org/"); });
|
||||||
append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r Manual")), _(L("Open the Slic3r manual in your browser")),
|
append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r &Manual")), _(L("Open the Slic3r manual in your browser")),
|
||||||
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://manual.slic3r.org/"); });
|
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://manual.slic3r.org/"); });
|
||||||
helpMenu->AppendSeparator();
|
helpMenu->AppendSeparator();
|
||||||
append_menu_item(helpMenu, wxID_ANY, _(L("System Info")), _(L("Show system information")),
|
append_menu_item(helpMenu, wxID_ANY, _(L("System &Info")), _(L("Show system information")),
|
||||||
[this](wxCommandEvent&) { wxGetApp().system_info(); });
|
[this](wxCommandEvent&) { wxGetApp().system_info(); });
|
||||||
append_menu_item(helpMenu, wxID_ANY, _(L("Show Configuration Folder")), _(L("Show user configuration folder (datadir)")),
|
append_menu_item(helpMenu, wxID_ANY, _(L("Show &Configuration Folder")), _(L("Show user configuration folder (datadir)")),
|
||||||
[this](wxCommandEvent&) { Slic3r::GUI::desktop_open_datadir_folder(); });
|
[this](wxCommandEvent&) { Slic3r::GUI::desktop_open_datadir_folder(); });
|
||||||
append_menu_item(helpMenu, wxID_ANY, _(L("Report an Issue")), _(L("Report an issue on the Slic3r Prusa Edition")),
|
append_menu_item(helpMenu, wxID_ANY, _(L("Report an I&ssue")), _(L("Report an issue on the Slic3r Prusa Edition")),
|
||||||
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://github.com/prusa3d/slic3r/issues/new"); });
|
[this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://github.com/prusa3d/slic3r/issues/new"); });
|
||||||
append_menu_item(helpMenu, wxID_ANY, _(L("About Slic3r")), _(L("Show about dialog")),
|
append_menu_item(helpMenu, wxID_ANY, _(L("&About Slic3r")), _(L("Show about dialog")),
|
||||||
[this](wxCommandEvent&) { Slic3r::GUI::about(); });
|
[this](wxCommandEvent&) { Slic3r::GUI::about(); });
|
||||||
helpMenu->AppendSeparator();
|
helpMenu->AppendSeparator();
|
||||||
append_menu_item(helpMenu, wxID_ANY, _(L("Keyboard Shortcuts")) + "\t\xA0?", _(L("Show the list of the keyboard shortcuts")),
|
append_menu_item(helpMenu, wxID_ANY, _(L("&Keyboard Shortcuts")) + "\t\xA0?", _(L("Show the list of the keyboard shortcuts")),
|
||||||
[this](wxCommandEvent&) { wxGetApp().keyboard_shortcuts(); });
|
[this](wxCommandEvent&) { wxGetApp().keyboard_shortcuts(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,17 +427,18 @@ void MainFrame::init_menubar()
|
|||||||
// assign menubar to frame after appending items, otherwise special items
|
// assign menubar to frame after appending items, otherwise special items
|
||||||
// will not be handled correctly
|
// will not be handled correctly
|
||||||
auto menubar = new wxMenuBar();
|
auto menubar = new wxMenuBar();
|
||||||
menubar->Append(fileMenu, L("&File"));
|
menubar->Append(fileMenu, _(L("&File")));
|
||||||
if (editMenu) menubar->Append(editMenu, L("&Edit"));
|
if (editMenu) menubar->Append(editMenu, _(L("&Edit")));
|
||||||
menubar->Append(windowMenu, L("&Window"));
|
menubar->Append(windowMenu, _(L("&Window")));
|
||||||
if (viewMenu) menubar->Append(viewMenu, L("&View"));
|
if (viewMenu) menubar->Append(viewMenu, _(L("&View")));
|
||||||
// Add additional menus from C++
|
// Add additional menus from C++
|
||||||
wxGetApp().add_config_menu(menubar);
|
wxGetApp().add_config_menu(menubar);
|
||||||
menubar->Append(helpMenu, L("&Help"));
|
menubar->Append(helpMenu, _(L("&Help")));
|
||||||
SetMenuBar(menubar);
|
SetMenuBar(menubar);
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
// This fixes a bug (?) on Mac OS where the quit command doesn't emit window close events
|
// This fixes a bug on Mac OS where the quit command doesn't emit window close events
|
||||||
|
// wx bug: https://trac.wxwidgets.org/ticket/18328
|
||||||
wxMenu *apple_menu = menubar->OSXGetAppleMenu();
|
wxMenu *apple_menu = menubar->OSXGetAppleMenu();
|
||||||
if (apple_menu != nullptr) {
|
if (apple_menu != nullptr) {
|
||||||
apple_menu->Bind(wxEVT_MENU, [this](wxCommandEvent &) {
|
apple_menu->Bind(wxEVT_MENU, [this](wxCommandEvent &) {
|
||||||
@@ -551,7 +549,7 @@ void MainFrame::quick_slice(const int qs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// show processbar dialog
|
// show processbar dialog
|
||||||
m_progress_dialog = new wxProgressDialog(_(L("Slicing…")), _(L("Processing ")) + input_file_basename + "…",
|
m_progress_dialog = new wxProgressDialog(_(L("Slicing")) + dots, _(L("Processing ")) + input_file_basename + "…",
|
||||||
100, this, 4);
|
100, this, 4);
|
||||||
m_progress_dialog->Pulse();
|
m_progress_dialog->Pulse();
|
||||||
{
|
{
|
||||||
@@ -847,7 +845,7 @@ void MainFrame::on_value_changed(wxCommandEvent& event)
|
|||||||
void MainFrame::update_ui_from_settings()
|
void MainFrame::update_ui_from_settings()
|
||||||
{
|
{
|
||||||
bool bp_on = wxGetApp().app_config->get("background_processing") == "1";
|
bool bp_on = wxGetApp().app_config->get("background_processing") == "1";
|
||||||
m_menu_item_reslice_now->Enable(!bp_on);
|
// m_menu_item_reslice_now->Enable(!bp_on);
|
||||||
m_plater->sidebar().show_reslice(!bp_on);
|
m_plater->sidebar().show_reslice(!bp_on);
|
||||||
m_plater->sidebar().Layout();
|
m_plater->sidebar().Layout();
|
||||||
if (m_plater)
|
if (m_plater)
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class MainFrame : public wxFrame
|
|||||||
bool can_save() const;
|
bool can_save() const;
|
||||||
bool can_export_model() const;
|
bool can_export_model() const;
|
||||||
bool can_export_gcode() const;
|
bool can_export_gcode() const;
|
||||||
|
bool can_slice() const;
|
||||||
bool can_change_view() const;
|
bool can_change_view() const;
|
||||||
bool can_select() const;
|
bool can_select() const;
|
||||||
bool can_delete() const;
|
bool can_delete() const;
|
||||||
|
|||||||
@@ -231,11 +231,11 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n
|
|||||||
wxSizer* sizer_tmp = sizer;
|
wxSizer* sizer_tmp = sizer;
|
||||||
// add label if any
|
// add label if any
|
||||||
if (option.label != "") {
|
if (option.label != "") {
|
||||||
wxString str_label = _(option.label);
|
// wxString str_label = _(option.label);
|
||||||
//! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
|
//! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
|
||||||
// wxString str_label = (option.label == "Top" || option.label == "Bottom") ?
|
wxString str_label = (option.label == "Top" || option.label == "Bottom") ?
|
||||||
// wxGETTEXT_IN_CONTEXT("Layers", wxString(option.label.c_str()):
|
wxGETTEXT_IN_CONTEXT("Layers", wxString(option.label)) :
|
||||||
// L_str(option.label);
|
_(option.label);
|
||||||
label = new wxStaticText(parent(), wxID_ANY, str_label + ":", wxDefaultPosition, wxDefaultSize);
|
label = new wxStaticText(parent(), wxID_ANY, str_label + ":", wxDefaultPosition, wxDefaultSize);
|
||||||
label->SetFont(label_font);
|
label->SetFont(label_font);
|
||||||
sizer_tmp->Add(label, 0, /*wxALIGN_RIGHT |*/ wxALIGN_CENTER_VERTICAL, 0);
|
sizer_tmp->Add(label, 0, /*wxALIGN_RIGHT |*/ wxALIGN_CENTER_VERTICAL, 0);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef slic3r_OptionsGroup_hpp_
|
#ifndef slic3r_OptionsGroup_hpp_
|
||||||
#define slic3r_OptionsGroup_hpp_
|
#define slic3r_OptionsGroup_hpp_
|
||||||
|
|
||||||
#include <wx/wx.h>
|
//#include <wx/wx.h>
|
||||||
#include <wx/stattext.h>
|
#include <wx/stattext.h>
|
||||||
#include <wx/settings.h>
|
#include <wx/settings.h>
|
||||||
//#include <wx/window.h>
|
//#include <wx/window.h>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include "libslic3r/Config.hpp"
|
#include "libslic3r/Config.hpp"
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
#include "libslic3r/libslic3r.h"
|
// #include "libslic3r/libslic3r.h"
|
||||||
|
|
||||||
#include "Field.hpp"
|
#include "Field.hpp"
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
|
|||||||
+23
-23
@@ -114,7 +114,7 @@ ObjectInfo::ObjectInfo(wxWindow *parent) :
|
|||||||
grid_sizer->AddGrowableCol(3, 1);
|
grid_sizer->AddGrowableCol(3, 1);
|
||||||
|
|
||||||
auto init_info_label = [parent, grid_sizer](wxStaticText **info_label, wxString text_label) {
|
auto init_info_label = [parent, grid_sizer](wxStaticText **info_label, 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, "");
|
*info_label = new wxStaticText(parent, wxID_ANY, "");
|
||||||
(*info_label)->SetFont(wxGetApp().small_font());
|
(*info_label)->SetFont(wxGetApp().small_font());
|
||||||
@@ -122,13 +122,13 @@ ObjectInfo::ObjectInfo(wxWindow *parent) :
|
|||||||
grid_sizer->Add(*info_label, 0);
|
grid_sizer->Add(*info_label, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
init_info_label(&info_size, _(L("Size:")));
|
init_info_label(&info_size, _(L("Size")));
|
||||||
init_info_label(&info_volume, _(L("Volume:")));
|
init_info_label(&info_volume, _(L("Volume")));
|
||||||
init_info_label(&info_facets, _(L("Facets:")));
|
init_info_label(&info_facets, _(L("Facets")));
|
||||||
init_info_label(&info_materials, _(L("Materials:")));
|
init_info_label(&info_materials, _(L("Materials")));
|
||||||
Add(grid_sizer, 0, wxEXPAND);
|
Add(grid_sizer, 0, wxEXPAND);
|
||||||
|
|
||||||
auto *info_manifold_text = new wxStaticText(parent, wxID_ANY, _(L("Manifold:")));
|
auto *info_manifold_text = new wxStaticText(parent, wxID_ANY, _(L("Manifold")));
|
||||||
info_manifold_text->SetFont(wxGetApp().small_font());
|
info_manifold_text->SetFont(wxGetApp().small_font());
|
||||||
info_manifold = new wxStaticText(parent, wxID_ANY, "");
|
info_manifold = new wxStaticText(parent, wxID_ANY, "");
|
||||||
info_manifold->SetFont(wxGetApp().small_font());
|
info_manifold->SetFont(wxGetApp().small_font());
|
||||||
@@ -602,7 +602,7 @@ Sidebar::Sidebar(Plater *parent)
|
|||||||
scrolled_sizer->Add(p->sliced_info, 0, wxEXPAND | wxTOP | wxLEFT, 20);
|
scrolled_sizer->Add(p->sliced_info, 0, wxEXPAND | wxTOP | wxLEFT, 20);
|
||||||
|
|
||||||
// Buttons underneath the scrolled area
|
// Buttons underneath the scrolled area
|
||||||
p->btn_export_gcode = new wxButton(this, wxID_ANY, _(L("Export G-code…")));
|
p->btn_export_gcode = new wxButton(this, wxID_ANY, _(L("Export G-code")) + dots);
|
||||||
p->btn_export_gcode->SetFont(wxGetApp().bold_font());
|
p->btn_export_gcode->SetFont(wxGetApp().bold_font());
|
||||||
p->btn_reslice = new wxButton(this, wxID_ANY, _(L("Slice now")));
|
p->btn_reslice = new wxButton(this, wxID_ANY, _(L("Slice now")));
|
||||||
p->btn_reslice->SetFont(wxGetApp().bold_font());
|
p->btn_reslice->SetFont(wxGetApp().bold_font());
|
||||||
@@ -792,7 +792,7 @@ void Sidebar::show_info_sizer()
|
|||||||
wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors)")), errors);
|
wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors)")), errors);
|
||||||
p->object_info->info_manifold->SetLabel(tooltip);
|
p->object_info->info_manifold->SetLabel(tooltip);
|
||||||
|
|
||||||
tooltip += wxString::Format(_(L(":\n%d degenerate facets, %d edges fixed, %d facets removed, "
|
tooltip += ":\n" + wxString::Format(_(L("%d degenerate facets, %d edges fixed, %d facets removed, "
|
||||||
"%d facets added, %d facets reversed, %d backwards edges")),
|
"%d facets added, %d facets reversed, %d backwards edges")),
|
||||||
stats.degenerate_facets, stats.edges_fixed, stats.facets_removed,
|
stats.degenerate_facets, stats.edges_fixed, stats.facets_removed,
|
||||||
stats.facets_added, stats.facets_reversed, stats.backwards_edges);
|
stats.facets_added, stats.facets_reversed, stats.backwards_edges);
|
||||||
@@ -849,7 +849,7 @@ void Sidebar::show_sliced_info_sizer(const bool show)
|
|||||||
if (ps.estimated_normal_print_time == "N/A" && ps.estimated_silent_print_time == "N/A")
|
if (ps.estimated_normal_print_time == "N/A" && ps.estimated_silent_print_time == "N/A")
|
||||||
p->sliced_info->SetTextAndShow(siEstimatedTime, "N/A");
|
p->sliced_info->SetTextAndShow(siEstimatedTime, "N/A");
|
||||||
else {
|
else {
|
||||||
new_label = "Estimated printing time :";
|
new_label = _(L("Estimated printing time")) +" :";
|
||||||
info_text = "";
|
info_text = "";
|
||||||
if (ps.estimated_normal_print_time != "N/A") {
|
if (ps.estimated_normal_print_time != "N/A") {
|
||||||
new_label += wxString::Format("\n - %s", _(L("normal mode")));
|
new_label += wxString::Format("\n - %s", _(L("normal mode")));
|
||||||
@@ -1306,7 +1306,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto loading = _(L("Loading…"));
|
const auto loading = _(L("Loading")) + dots;
|
||||||
wxProgressDialog dlg(loading, loading);
|
wxProgressDialog dlg(loading, loading);
|
||||||
dlg.Pulse();
|
dlg.Pulse();
|
||||||
|
|
||||||
@@ -1367,14 +1367,14 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||||||
// The model should now be initialized
|
// The model should now be initialized
|
||||||
|
|
||||||
if (model.looks_like_multipart_object()) {
|
if (model.looks_like_multipart_object()) {
|
||||||
// wxMessageDialog dlg(q, _(L(
|
wxMessageDialog dlg(q, _(L(
|
||||||
// "This file contains several objects positioned at multiple heights. "
|
"This file contains several objects positioned at multiple heights. "
|
||||||
// "Instead of considering them as multiple objects, should I consider\n"
|
"Instead of considering them as multiple objects, should I consider\n"
|
||||||
// "this file as a single object having multiple parts?\n"
|
"this file as a single object having multiple parts?\n"
|
||||||
// )), _(L("Multi-part object detected")), wxICON_WARNING | wxYES | wxNO);
|
)), _(L("Multi-part object detected")), wxICON_WARNING | wxYES | wxNO);
|
||||||
// if (dlg.ShowModal() == wxID_YES) {
|
if (dlg.ShowModal() == wxID_YES) {
|
||||||
model.convert_multipart_object(nozzle_dmrs->values.size());
|
model.convert_multipart_object(nozzle_dmrs->values.size());
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type_3mf || type_any_amf) {
|
if (type_3mf || type_any_amf) {
|
||||||
@@ -2350,14 +2350,14 @@ bool Plater::priv::init_object_menu()
|
|||||||
|
|
||||||
bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/)
|
bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/)
|
||||||
{
|
{
|
||||||
wxMenuItem* item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete\tDel")), _(L("Remove the selected object")),
|
wxMenuItem* item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")),
|
||||||
[this](wxCommandEvent&) { q->remove_selected(); }, "brick_delete.png");
|
[this](wxCommandEvent&) { q->remove_selected(); }, "brick_delete.png");
|
||||||
if (!is_part){
|
if (!is_part){
|
||||||
wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _(L("Increase copies\t+")), _(L("Place one more copy of the selected object")),
|
wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _(L("Increase copies")) + "\t+", _(L("Place one more copy of the selected object")),
|
||||||
[this](wxCommandEvent&) { q->increase_instances(); }, "add.png");
|
[this](wxCommandEvent&) { q->increase_instances(); }, "add.png");
|
||||||
wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _(L("Decrease copies\t-")), _(L("Remove one copy of the selected object")),
|
wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _(L("Decrease copies")) + "\t-", _(L("Remove one copy of the selected object")),
|
||||||
[this](wxCommandEvent&) { q->decrease_instances(); }, "delete.png");
|
[this](wxCommandEvent&) { q->decrease_instances(); }, "delete.png");
|
||||||
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of copies…")), _(L("Change the number of copies of the selected object")),
|
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of copies")) + dots, _(L("Change the number of copies of the selected object")),
|
||||||
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "textfield.png");
|
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "textfield.png");
|
||||||
if (q != nullptr)
|
if (q != nullptr)
|
||||||
{
|
{
|
||||||
@@ -2370,7 +2370,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
|
|||||||
append_menu_item(menu, wxID_ANY, _(L("Reload from Disk")), _(L("Reload the selected file from Disk")),
|
append_menu_item(menu, wxID_ANY, _(L("Reload from Disk")), _(L("Reload the selected file from Disk")),
|
||||||
[this](wxCommandEvent&) { reload_from_disk(); });
|
[this](wxCommandEvent&) { reload_from_disk(); });
|
||||||
|
|
||||||
append_menu_item(menu, wxID_ANY, _(L("Export object as STL…")), _(L("Export this single object as STL file")),
|
append_menu_item(menu, wxID_ANY, _(L("Export object as STL")) + dots, _(L("Export this single object as STL file")),
|
||||||
[this](wxCommandEvent&) { q->export_stl(true); });
|
[this](wxCommandEvent&) { q->export_stl(true); });
|
||||||
}
|
}
|
||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
@@ -2414,7 +2414,7 @@ bool Plater::priv::complit_init_object_menu()
|
|||||||
// append_menu_item(&object_menu, wxID_ANY, _(L("Reload from Disk")), _(L("Reload the selected file from Disk")),
|
// append_menu_item(&object_menu, wxID_ANY, _(L("Reload from Disk")), _(L("Reload the selected file from Disk")),
|
||||||
// [this](wxCommandEvent&) { reload_from_disk(); });
|
// [this](wxCommandEvent&) { reload_from_disk(); });
|
||||||
//
|
//
|
||||||
// append_menu_item(&object_menu, wxID_ANY, _(L("Export object as STL…")), _(L("Export this single object as STL file")),
|
// append_menu_item(&object_menu, wxID_ANY, _(L("Export object as STL")) + dots, _(L("Export this single object as STL file")),
|
||||||
// [this](wxCommandEvent&) { q->export_stl(true); });
|
// [this](wxCommandEvent&) { q->export_stl(true); });
|
||||||
|
|
||||||
// Append "Add..." popupmenu
|
// Append "Add..." popupmenu
|
||||||
|
|||||||
@@ -1153,11 +1153,11 @@ std::vector<std::string> PresetCollection::merge_presets(PresetCollection &&othe
|
|||||||
std::string PresetCollection::name() const
|
std::string PresetCollection::name() const
|
||||||
{
|
{
|
||||||
switch (this->type()) {
|
switch (this->type()) {
|
||||||
case Preset::TYPE_PRINT: return "print";
|
case Preset::TYPE_PRINT: return L("print");
|
||||||
case Preset::TYPE_FILAMENT: return "filament";
|
case Preset::TYPE_FILAMENT: return L("filament");
|
||||||
case Preset::TYPE_SLA_PRINT: return "SLA print";
|
case Preset::TYPE_SLA_PRINT: return L("SLA print");
|
||||||
case Preset::TYPE_SLA_MATERIAL: return "SLA material";
|
case Preset::TYPE_SLA_MATERIAL: return L("SLA material");
|
||||||
case Preset::TYPE_PRINTER: return "printer";
|
case Preset::TYPE_PRINTER: return L("printer");
|
||||||
default: return "invalid";
|
default: return "invalid";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ SysInfoDialog::SysInfoDialog()
|
|||||||
main_sizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3);
|
main_sizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3);
|
||||||
|
|
||||||
// this->Bind(wxEVT_LEFT_DOWN, &SysInfoDialog::onCloseDialog, this);
|
// this->Bind(wxEVT_LEFT_DOWN, &SysInfoDialog::onCloseDialog, this);
|
||||||
logo->Bind(wxEVT_LEFT_DOWN, &SysInfoDialog::onCloseDialog, this);
|
// logo->Bind(wxEVT_LEFT_DOWN, &SysInfoDialog::onCloseDialog, this);
|
||||||
|
|
||||||
SetSizer(main_sizer);
|
SetSizer(main_sizer);
|
||||||
main_sizer->SetSizeHints(this);
|
main_sizer->SetSizeHints(this);
|
||||||
|
|||||||
+12
-11
@@ -2009,7 +2009,7 @@ PageShp TabPrinter::build_kinematics_page()
|
|||||||
|
|
||||||
if (m_use_silent_mode) {
|
if (m_use_silent_mode) {
|
||||||
// Legend for OptionsGroups
|
// Legend for OptionsGroups
|
||||||
auto optgroup = page->new_optgroup(_(L("")));
|
auto optgroup = page->new_optgroup("");
|
||||||
optgroup->set_show_modified_btns_val(false);
|
optgroup->set_show_modified_btns_val(false);
|
||||||
optgroup->label_width = 230;
|
optgroup->label_width = 230;
|
||||||
auto line = Line{ "", "" };
|
auto line = Line{ "", "" };
|
||||||
@@ -2559,19 +2559,20 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr
|
|||||||
std::string type_name = presets->name();
|
std::string type_name = presets->name();
|
||||||
wxString tab = " ";
|
wxString tab = " ";
|
||||||
wxString name = old_preset.is_default ?
|
wxString name = old_preset.is_default ?
|
||||||
_(L("Default ")) + type_name + _(L(" preset")) :
|
wxString::Format(_(L("Default preset (%s)")), _(type_name)) : //_(L("Default ")) + type_name + _(L(" preset")) :
|
||||||
(type_name + _(L(" preset\n")) + tab + old_preset.name);
|
wxString::Format(_(L("Preset (%s)")), _(type_name)) + "\n" + tab + old_preset.name; //type_name + _(L(" preset\n")) + tab + old_preset.name;
|
||||||
|
|
||||||
// Collect descriptions of the dirty options.
|
// Collect descriptions of the dirty options.
|
||||||
wxString changes;
|
wxString changes;
|
||||||
for (const std::string &opt_key : presets->current_dirty_options()) {
|
for (const std::string &opt_key : presets->current_dirty_options()) {
|
||||||
const ConfigOptionDef &opt = m_config->def()->options.at(opt_key);
|
const ConfigOptionDef &opt = m_config->def()->options.at(opt_key);
|
||||||
std::string name = "";
|
/*std::string*/wxString name = "";
|
||||||
if (! opt.category.empty())
|
if (! opt.category.empty())
|
||||||
name += opt.category + " > ";
|
name += _(opt.category) + " > ";
|
||||||
name += !opt.full_label.empty() ?
|
name += !opt.full_label.empty() ?
|
||||||
opt.full_label :
|
_(opt.full_label) :
|
||||||
opt.label;
|
_(opt.label);
|
||||||
changes += tab + from_u8(name) + "\n";
|
changes += tab + /*from_u8*/(name) + "\n";
|
||||||
}
|
}
|
||||||
// Show a confirmation dialog with the list of dirty options.
|
// Show a confirmation dialog with the list of dirty options.
|
||||||
wxString message = name + "\n\n";
|
wxString message = name + "\n\n";
|
||||||
@@ -2585,7 +2586,7 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr
|
|||||||
message += _(L("and it has the following unsaved changes:"));
|
message += _(L("and it has the following unsaved changes:"));
|
||||||
}
|
}
|
||||||
auto confirm = new wxMessageDialog(parent(),
|
auto confirm = new wxMessageDialog(parent(),
|
||||||
message + "\n" + changes + _(L("\n\nDiscard changes and continue anyway?")),
|
message + "\n" + changes + "\n\n" + _(L("Discard changes and continue anyway?")),
|
||||||
_(L("Unsaved Changes")), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
|
_(L("Unsaved Changes")), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
|
||||||
return confirm->ShowModal() == wxID_YES;
|
return confirm->ShowModal() == wxID_YES;
|
||||||
}
|
}
|
||||||
@@ -2597,8 +2598,8 @@ bool Tab::may_switch_to_SLA_preset()
|
|||||||
if (wxGetApp().obj_list()->has_multi_part_objects())
|
if (wxGetApp().obj_list()->has_multi_part_objects())
|
||||||
{
|
{
|
||||||
show_info( parent(),
|
show_info( parent(),
|
||||||
_(L("It's impossible to print multi-part object(s) with SLA technology.")) +
|
_(L("It's impossible to print multi-part object(s) with SLA technology.")) + "\n\n" +
|
||||||
_(L("\n\nPlease check your object list before preset changing.")),
|
_(L("Please check your object list before preset changing.")),
|
||||||
_(L("Attention!")) );
|
_(L("Attention!")) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user