mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-16 11:17:51 -06:00
ENH: step mesh operation adjustment
1.Put commctrl.h into pch precompilation(OCCT conflicts) 2.Replace input wxWidgets to support loss focus verification(STUDIO-8101) 3.Optimize slider interaction and trigger mesh when push up slider(STUDIO-8099) 4.Optimize step loading method, separate import of step and mesh 5.Fix dialog cancel button logic; 6.mesh tasks into sub-threads to prevent blocking the UI; JIRA: STUDIO-8101 STUDIO-8099 Change-Id: I50bbb43953a5128f358c6880032d20693531333b (cherry picked from commit ed7ab6b505a2becf8f38edb3c43b96e51eac3317)
This commit is contained in:
parent
e1477e642c
commit
f91b520bb8
11 changed files with 326 additions and 94 deletions
|
@ -33,6 +33,8 @@
|
|||
#include "TopExp_Explorer.hxx"
|
||||
#include "TopExp_Explorer.hxx"
|
||||
#include "BRep_Tool.hxx"
|
||||
#include "BRepTools.hxx"
|
||||
#include <IMeshTools_Parameters.hxx>
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
@ -163,13 +165,6 @@ int StepPreProcessor::preNum(const unsigned char byte) {
|
|||
return num;
|
||||
}
|
||||
|
||||
struct NamedSolid {
|
||||
NamedSolid(const TopoDS_Shape& s,
|
||||
const std::string& n) : solid{s}, name{n} {}
|
||||
const TopoDS_Shape solid;
|
||||
const std::string name;
|
||||
};
|
||||
|
||||
static void getNamedSolids(const TopLoc_Location& location, const std::string& prefix,
|
||||
unsigned int& id, const Handle(XCAFDoc_ShapeTool) shapeTool,
|
||||
const TDF_Label label, std::vector<NamedSolid>& namedSolids) {
|
||||
|
@ -324,7 +319,7 @@ bool load_step(const char *path, Model *model, bool& is_cancel,
|
|||
}
|
||||
// BBS: copy triangles
|
||||
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
||||
Standard_Integer anId[3];
|
||||
Standard_Integer anId[3] = {};
|
||||
for (Standard_Integer aTriIter = 1; aTriIter <= aTriangulation->NbTriangles(); ++aTriIter) {
|
||||
Poly_Triangle aTri = aTriangulation->Triangle(aTriIter);
|
||||
|
||||
|
@ -403,4 +398,104 @@ bool load_step(const char *path, Model *model, bool& is_cancel,
|
|||
return true;
|
||||
}
|
||||
|
||||
Step::Step(fs::path path, ImportStepProgressFn stepFn, StepIsUtf8Fn isUtf8Fn):
|
||||
m_stepFn(stepFn),
|
||||
m_utf8Fn(isUtf8Fn)
|
||||
{
|
||||
m_path = path.string();
|
||||
m_app->NewDocument(TCollection_ExtendedString("BinXCAF"), m_doc);
|
||||
}
|
||||
|
||||
Step::Step(std::string path, ImportStepProgressFn stepFn, StepIsUtf8Fn isUtf8Fn) :
|
||||
m_path(path),
|
||||
m_stepFn(stepFn),
|
||||
m_utf8Fn(isUtf8Fn)
|
||||
{
|
||||
m_app->NewDocument(TCollection_ExtendedString("BinXCAF"), m_doc);
|
||||
}
|
||||
|
||||
bool Step::load()
|
||||
{
|
||||
if (!StepPreProcessor::isUtf8File(m_path.c_str()) && m_utf8Fn) {
|
||||
m_utf8Fn(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
STEPCAFControl_Reader reader;
|
||||
reader.SetNameMode(true);
|
||||
IFSelect_ReturnStatus stat = reader.ReadFile(m_path.c_str());
|
||||
if (stat != IFSelect_RetDone || !reader.Transfer(m_doc)) {
|
||||
m_app->Close(m_doc);
|
||||
return false;
|
||||
}
|
||||
m_shape_tool = XCAFDoc_DocumentTool::ShapeTool(m_doc->Main());
|
||||
TDF_LabelSequence topLevelShapes;
|
||||
m_shape_tool->GetFreeShapes(topLevelShapes);
|
||||
unsigned int id{ 1 };
|
||||
Standard_Integer topShapeLength = topLevelShapes.Length() + 1;
|
||||
for (Standard_Integer iLabel = 1; iLabel < topShapeLength; ++iLabel) {
|
||||
getNamedSolids(TopLoc_Location{}, "", id, m_shape_tool, topLevelShapes.Value(iLabel), m_name_solids);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Step::clean_mesh_data()
|
||||
{
|
||||
for (const auto& name_solid : m_name_solids) {
|
||||
BRepTools::Clean(name_solid.solid);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Step::get_triangle_num(double linear_defletion, double angle_defletion)
|
||||
{
|
||||
unsigned int tri_num = 0;
|
||||
Handle(StepProgressIncdicator) progress = new StepProgressIncdicator(m_stop_mesh);
|
||||
clean_mesh_data();
|
||||
IMeshTools_Parameters param;
|
||||
param.Deflection = linear_defletion;
|
||||
param.Angle = angle_defletion;
|
||||
param.InParallel = true;
|
||||
for (int i = 0; i < m_name_solids.size(); ++i) {
|
||||
BRepMesh_IncrementalMesh mesh(m_name_solids[i].solid, param, progress->Start());
|
||||
for (TopExp_Explorer anExpSF(m_name_solids[i].solid, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) {
|
||||
TopLoc_Location aLoc;
|
||||
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(TopoDS::Face(anExpSF.Current()), aLoc);
|
||||
if (!aTriangulation.IsNull()) {
|
||||
tri_num += aTriangulation->NbTriangles();
|
||||
}
|
||||
}
|
||||
if (m_stop_mesh.load()) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return tri_num;
|
||||
}
|
||||
|
||||
unsigned int Step::get_triangle_num_tbb(double linear_defletion, double angle_defletion)
|
||||
{
|
||||
unsigned int tri_num = 0;
|
||||
clean_mesh_data();
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, m_name_solids.size()),
|
||||
[&](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t i = range.begin(); i < range.end(); i++) {
|
||||
unsigned int solids_tri_num = 0;
|
||||
BRepMesh_IncrementalMesh mesh(m_name_solids[i].solid, linear_defletion, false, angle_defletion, true);
|
||||
for (TopExp_Explorer anExpSF(m_name_solids[i].solid, TopAbs_FACE); anExpSF.More(); anExpSF.Next()) {
|
||||
TopLoc_Location aLoc;
|
||||
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(TopoDS::Face(anExpSF.Current()), aLoc);
|
||||
if (!aTriangulation.IsNull()) {
|
||||
solids_tri_num += aTriangulation->NbTriangles();
|
||||
}
|
||||
}
|
||||
m_name_solids[i].tri_face_cout = solids_tri_num;
|
||||
}
|
||||
|
||||
});
|
||||
for (int i = 0; i < m_name_solids.size(); ++i) {
|
||||
tri_num += m_name_solids[i].tri_face_cout;
|
||||
}
|
||||
return tri_num;
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
#ifndef slic3r_Format_STEP_hpp_
|
||||
#define slic3r_Format_STEP_hpp_
|
||||
#include "XCAFDoc_DocumentTool.hxx"
|
||||
#include "XCAFApp_Application.hxx"
|
||||
#include "XCAFDoc_ShapeTool.hxx"
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <Message_ProgressIndicator.hxx>
|
||||
#include <atomic>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -16,6 +25,16 @@ const int LOAD_STEP_STAGE_UNIT_NUM = 5;
|
|||
typedef std::function<void(int load_stage, int current, int total, bool& cancel)> ImportStepProgressFn;
|
||||
typedef std::function<void(bool isUtf8)> StepIsUtf8Fn;
|
||||
|
||||
struct NamedSolid
|
||||
{
|
||||
NamedSolid(const TopoDS_Shape& s,
|
||||
const std::string& n) : solid{ s }, name{ n } {
|
||||
}
|
||||
const TopoDS_Shape solid;
|
||||
const std::string name;
|
||||
int tri_face_cout = 0;
|
||||
};
|
||||
|
||||
//BBS: Load an step file into a provided model.
|
||||
extern bool load_step(const char *path, Model *model,
|
||||
bool& is_cancel,
|
||||
|
@ -50,6 +69,41 @@ private:
|
|||
EncodedType m_encode_type = EncodedType::UTF8;
|
||||
};
|
||||
|
||||
class StepProgressIncdicator : public Message_ProgressIndicator
|
||||
{
|
||||
public:
|
||||
StepProgressIncdicator(std::atomic<bool>& stop_flag) : should_stop(stop_flag){}
|
||||
|
||||
Standard_Boolean UserBreak() override { return should_stop.load(); }
|
||||
|
||||
void Show(const Message_ProgressScope&, const Standard_Boolean) override {
|
||||
std::cout << "Progress: " << GetPosition() << "%" << std::endl;
|
||||
}
|
||||
private:
|
||||
std::atomic<bool>& should_stop;
|
||||
};
|
||||
|
||||
class Step
|
||||
{
|
||||
public:
|
||||
Step(fs::path path, ImportStepProgressFn stepFn = nullptr, StepIsUtf8Fn isUtf8Fn = nullptr);
|
||||
Step(std::string path, ImportStepProgressFn stepFn = nullptr, StepIsUtf8Fn isUtf8Fn = nullptr);
|
||||
bool load();
|
||||
unsigned int get_triangle_num(double linear_defletion, double angle_defletion);
|
||||
unsigned int get_triangle_num_tbb(double linear_defletion, double angle_defletion);
|
||||
void clean_mesh_data();
|
||||
|
||||
std::atomic<bool> m_stop_mesh;
|
||||
private:
|
||||
std::string m_path;
|
||||
ImportStepProgressFn m_stepFn;
|
||||
StepIsUtf8Fn m_utf8Fn;
|
||||
Handle(XCAFApp_Application) m_app = XCAFApp_Application::GetApplication();
|
||||
Handle(TDocStd_Document) m_doc;
|
||||
Handle(XCAFDoc_ShapeTool) m_shape_tool;
|
||||
std::vector<NamedSolid> m_name_solids;
|
||||
};
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
#endif /* slic3r_Format_STEP_hpp_ */
|
||||
|
|
|
@ -188,7 +188,7 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
|
|||
BBLProject * project,
|
||||
int plate_id,
|
||||
ObjImportColorFn objFn,
|
||||
std::function<int(double&, double&)> step_mesh_fn)
|
||||
std::function<int(Slic3r::Step&, double&, double&)> step_mesh_fn)
|
||||
{
|
||||
Model model;
|
||||
|
||||
|
@ -216,15 +216,15 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
|
|||
boost::algorithm::iends_with(input_file, ".step")) {
|
||||
double linear_defletion = 0.003;
|
||||
double angle_defletion = 0.5;
|
||||
Step step_file(input_file);
|
||||
step_file.load();
|
||||
if (step_mesh_fn) {
|
||||
if (step_mesh_fn(linear_defletion, angle_defletion) == -1) {
|
||||
result = false;
|
||||
goto end;
|
||||
if (step_mesh_fn(step_file, linear_defletion, angle_defletion) == -1) {
|
||||
Model empty_model;
|
||||
return empty_model;
|
||||
}
|
||||
}
|
||||
result = load_step(input_file.c_str(), &model, is_cb_cancel, linear_defletion, angle_defletion, stepFn, stepIsUtf8Fn);
|
||||
end:
|
||||
BOOST_LOG_TRIVIAL(info) << "Cancel step mesh dialog";
|
||||
} else if (boost::algorithm::iends_with(input_file, ".stl"))
|
||||
result = load_stl(input_file.c_str(), &model, nullptr, stlFn);
|
||||
else if (boost::algorithm::iends_with(input_file, ".oltp"))
|
||||
|
|
|
@ -1544,7 +1544,7 @@ public:
|
|||
BBLProject * project = nullptr,
|
||||
int plate_id = 0,
|
||||
ObjImportColorFn objFn = nullptr,
|
||||
std::function<int(double&, double&)> step_mesh_fn = nullptr
|
||||
std::function<int(Slic3r::Step&, double&, double&)> step_mesh_fn = nullptr
|
||||
);
|
||||
// BBS
|
||||
static bool obj_import_vertex_color_deal(const std::vector<unsigned char> &vertex_filament_ids, const unsigned char &first_extruder_id, Model *model);
|
||||
|
|
|
@ -38,7 +38,7 @@ Points CameraUtils::project(const Camera & camera,
|
|||
return result;
|
||||
}
|
||||
|
||||
Point CameraUtils::project(const Camera &camera, const Vec3d &point)
|
||||
Slic3r::Point CameraUtils::project(const Camera &camera, const Vec3d &point)
|
||||
{
|
||||
// IMPROVE: do it faster when you need it (inspire in project multi point)
|
||||
return project(camera, std::vector{point}).front();
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
/// <returns>projected points by camera into coordinate of camera.
|
||||
/// x(from left to right), y(from top to bottom)</returns>
|
||||
static Points project(const Camera& camera, const std::vector<Vec3d> &points);
|
||||
static Point project(const Camera& camera, const Vec3d &point);
|
||||
static Slic3r::Point project(const Camera& camera, const Vec3d &point);
|
||||
|
||||
/// <summary>
|
||||
/// Create hull around GLVolume in 2d space of camera
|
||||
|
|
|
@ -174,6 +174,8 @@ protected:
|
|||
void find_single();
|
||||
};
|
||||
|
||||
wxDECLARE_EVENT(wxEVT_THREAD_DONE, wxCommandEvent);
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
|
|
@ -4156,17 +4156,17 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||
filament_ids.clear();
|
||||
}
|
||||
};
|
||||
auto step_mesh = [this, &path, &is_user_cancel](double& linear_value, double& angle_value)-> int {
|
||||
auto step_mesh = [this, &path, &is_user_cancel](Slic3r::Step& file, double& linear_value, double& angle_value)-> int {
|
||||
if (boost::iends_with(path.string(), ".step") ||
|
||||
boost::iends_with(path.string(), ".stp")){
|
||||
StepMeshDialog mesh_dlg(nullptr, path);
|
||||
StepMeshDialog mesh_dlg(nullptr, file);
|
||||
if (mesh_dlg.ShowModal() == wxID_OK) {
|
||||
linear_value = mesh_dlg.get_linear_defletion();
|
||||
angle_value = mesh_dlg.get_angle_defletion();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
is_user_cancel = false;
|
||||
is_user_cancel = true;
|
||||
return -1;
|
||||
};
|
||||
model = Slic3r::Model:: read_from_file(
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
#include "StepMeshDialog.hpp"
|
||||
#include "BBLStatusBar.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
|
||||
#include <thread>
|
||||
#include <wx/event.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/slider.h>
|
||||
#include "GUI_App.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "Widgets/TextInput.hpp"
|
||||
#include <chrono>
|
||||
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
|
@ -14,7 +18,7 @@ static int _scale(const int val) { return val * Slic3r::GUI::wxGetApp().em_unit(
|
|||
static int _ITEM_WIDTH() { return _scale(30); }
|
||||
#define MIN_DIALOG_WIDTH FromDIP(400)
|
||||
#define SLIDER_WIDTH FromDIP(150)
|
||||
#define TEXT_CTRL_WIDTH FromDIP(40)
|
||||
#define TEXT_CTRL_WIDTH FromDIP(50)
|
||||
#define BUTTON_SIZE wxSize(FromDIP(58), FromDIP(24))
|
||||
#define BUTTON_BORDER FromDIP(int(400 - 58 * 2) / 8)
|
||||
#define SLIDER_SCALE(val) ((val) / 0.001)
|
||||
|
@ -23,18 +27,28 @@ static int _ITEM_WIDTH() { return _scale(30); }
|
|||
#define SLIDER_UNSCALE_10(val) ((val) * 0.01)
|
||||
#define LEFT_RIGHT_PADING FromDIP(20)
|
||||
|
||||
wxDEFINE_EVENT(wxEVT_THREAD_DONE, wxCommandEvent);
|
||||
|
||||
void StepMeshDialog::on_dpi_changed(const wxRect& suggested_rect) {
|
||||
};
|
||||
|
||||
bool StepMeshDialog:: validate_number_range(const wxString& value, double min, double max) {
|
||||
double num;
|
||||
if (!value.ToDouble(&num)) {
|
||||
double num = 0.0;
|
||||
if (value.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (!value.ToDouble(&num)) {
|
||||
return false;
|
||||
}
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (num >= min && num <= max);
|
||||
}
|
||||
|
||||
StepMeshDialog::StepMeshDialog(wxWindow* parent, fs::path file)
|
||||
StepMeshDialog::StepMeshDialog(wxWindow* parent, Slic3r::Step& file)
|
||||
: DPIDialog(parent ? parent : static_cast<wxWindow *>(wxGetApp().mainframe),
|
||||
wxID_ANY,
|
||||
_(L("Step file import parameters")),
|
||||
|
@ -42,6 +56,8 @@ StepMeshDialog::StepMeshDialog(wxWindow* parent, fs::path file)
|
|||
wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE /* | wxRESIZE_BORDER*/), m_file(file)
|
||||
{
|
||||
Bind(wxEVT_THREAD_DONE, &StepMeshDialog::on_task_done, this);
|
||||
|
||||
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico")
|
||||
% Slic3r::resources_dir()).str();
|
||||
SetIcon(wxIcon(Slic3r::encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
|
@ -64,34 +80,28 @@ StepMeshDialog::StepMeshDialog(wxWindow* parent, fs::path file)
|
|||
wxSize(SLIDER_WIDTH, -1),
|
||||
wxSL_HORIZONTAL);
|
||||
linear_sizer->Add(linear_slider, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(5));
|
||||
wxTextValidator valid_number(wxFILTER_NUMERIC);
|
||||
wxTextCtrl* linear_textctrl = new wxTextCtrl(this, wxID_ANY,
|
||||
m_linear_last,
|
||||
wxDefaultPosition, wxSize(TEXT_CTRL_WIDTH, -1),
|
||||
0, valid_number);
|
||||
linear_sizer->Add(linear_textctrl, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(5));
|
||||
// textctrl loss focus
|
||||
linear_textctrl->Bind(wxEVT_KILL_FOCUS, ([this, linear_textctrl](wxFocusEvent& e) {
|
||||
wxString value = linear_textctrl->GetValue();
|
||||
if(!validate_number_range(value, 0.001, 0.1)) {
|
||||
linear_textctrl->SetValue(m_linear_last);
|
||||
|
||||
auto linear_input = new ::TextInput(this, m_linear_last, wxEmptyString, wxEmptyString, wxDefaultPosition, wxSize(TEXT_CTRL_WIDTH, -1));
|
||||
linear_input->GetTextCtrl()->SetFont(Label::Body_12);
|
||||
linear_input->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
|
||||
linear_sizer->Add(linear_input, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(5));
|
||||
linear_input->Bind(wxEVT_KILL_FOCUS, ([this, linear_input](wxFocusEvent& e) {
|
||||
wxString value = linear_input->GetTextCtrl()->GetValue();
|
||||
if (validate_number_range(value, 0.001, 0.1)) {
|
||||
m_linear_last = value;
|
||||
update_mesh_number_text();
|
||||
} else {
|
||||
MessageDialog msg_dlg(nullptr, _L("Please input a valid value (0.001 < angle deflection < 0.1)"), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
linear_input->GetTextCtrl()->SetValue(m_linear_last);
|
||||
}
|
||||
m_linear_last = value;
|
||||
update_mesh_number_text();
|
||||
e.Skip();
|
||||
}));
|
||||
// slider bind textctrl
|
||||
linear_slider->Bind(wxEVT_SLIDER, ([this, linear_slider, linear_textctrl](wxCommandEvent& e) {
|
||||
double slider_value = SLIDER_UNSCALE(linear_slider->GetValue());
|
||||
linear_textctrl->SetValue(wxString::Format("%.3f", slider_value));
|
||||
m_linear_last = wxString::Format("%.3f", slider_value);
|
||||
update_mesh_number_text();
|
||||
}));
|
||||
// textctrl bind slider
|
||||
linear_textctrl->Bind(wxEVT_TEXT, ([this, linear_textctrl, linear_slider](wxCommandEvent& e) {
|
||||
linear_input->Bind(wxEVT_TEXT, ([this, linear_slider, linear_input](wxCommandEvent& e) {
|
||||
double slider_value_long;
|
||||
int slider_value;
|
||||
wxString value = linear_textctrl->GetValue();
|
||||
wxString value = linear_input->GetTextCtrl()->GetValue();
|
||||
if (value.ToDouble(&slider_value_long)) {
|
||||
slider_value = SLIDER_SCALE(slider_value_long);
|
||||
if (slider_value >= linear_slider->GetMin() && slider_value <= linear_slider->GetMax()) {
|
||||
|
@ -99,6 +109,15 @@ StepMeshDialog::StepMeshDialog(wxWindow* parent, fs::path file)
|
|||
}
|
||||
}
|
||||
}));
|
||||
linear_slider->Bind(wxEVT_SLIDER, ([this, linear_slider, linear_input](wxCommandEvent& e) {
|
||||
double slider_value = SLIDER_UNSCALE(linear_slider->GetValue());
|
||||
linear_input->GetTextCtrl()->SetValue(wxString::Format("%.3f", slider_value));
|
||||
m_linear_last = wxString::Format("%.3f", slider_value);
|
||||
}));
|
||||
linear_slider->Bind(wxEVT_LEFT_UP, ([this](wxMouseEvent& e) {
|
||||
update_mesh_number_text();
|
||||
e.Skip();
|
||||
}));
|
||||
|
||||
bSizer->Add(linear_sizer, 1, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, LEFT_RIGHT_PADING);
|
||||
|
||||
|
@ -114,33 +133,28 @@ StepMeshDialog::StepMeshDialog(wxWindow* parent, fs::path file)
|
|||
wxSize(SLIDER_WIDTH, -1),
|
||||
wxSL_HORIZONTAL);
|
||||
angle_sizer->Add(angle_slider, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(5));
|
||||
wxTextCtrl* angle_textctrl = new wxTextCtrl(this, wxID_ANY,
|
||||
m_angle_last,
|
||||
wxDefaultPosition, wxSize(TEXT_CTRL_WIDTH, -1),
|
||||
0, valid_number);
|
||||
angle_sizer->Add(angle_textctrl, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(5));
|
||||
// textctrl loss focus
|
||||
angle_textctrl->Bind(wxEVT_KILL_FOCUS, ([this, angle_textctrl](wxFocusEvent& e) {
|
||||
wxString value = angle_textctrl->GetValue();
|
||||
if (!validate_number_range(value, 0.01, 1)) {
|
||||
angle_textctrl->SetValue(m_angle_last);
|
||||
|
||||
auto angle_input = new::TextInput(this, m_angle_last, wxEmptyString, wxEmptyString, wxDefaultPosition, wxSize(TEXT_CTRL_WIDTH, -1));
|
||||
angle_input->GetTextCtrl()->SetFont(Label::Body_12);
|
||||
angle_input->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
|
||||
angle_sizer->Add(angle_input, 0, wxALIGN_RIGHT | wxLEFT, FromDIP(5));
|
||||
angle_input->Bind(wxEVT_KILL_FOCUS, ([this, angle_input](wxFocusEvent& e) {
|
||||
wxString value = angle_input->GetTextCtrl()->GetValue();
|
||||
if (validate_number_range(value, 0.01, 1)) {
|
||||
m_angle_last = value;
|
||||
update_mesh_number_text();
|
||||
} else {
|
||||
MessageDialog msg_dlg(nullptr, _L("Please input a valid value (0.01 < angle deflection < 1.0)"), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
angle_input->GetTextCtrl()->SetValue(m_angle_last);
|
||||
}
|
||||
m_angle_last = value;
|
||||
update_mesh_number_text();
|
||||
e.Skip();
|
||||
}));
|
||||
// slider bind textctrl
|
||||
angle_slider->Bind(wxEVT_SLIDER, ([this, angle_slider, angle_textctrl](wxCommandEvent& e) {
|
||||
double slider_value = SLIDER_UNSCALE_10(angle_slider->GetValue());
|
||||
angle_textctrl->SetValue(wxString::Format("%.2f", slider_value));
|
||||
m_angle_last = wxString::Format("%.2f", slider_value);
|
||||
update_mesh_number_text();
|
||||
}));
|
||||
// textctrl bind slider
|
||||
linear_textctrl->Bind(wxEVT_TEXT, ([this, angle_slider, angle_textctrl](wxCommandEvent& e) {
|
||||
angle_input->Bind(wxEVT_TEXT, ([this, angle_slider, angle_input](wxCommandEvent& e) {
|
||||
double slider_value_long;
|
||||
int slider_value;
|
||||
wxString value = angle_textctrl->GetValue();
|
||||
wxString value = angle_input->GetTextCtrl()->GetValue();
|
||||
if (value.ToDouble(&slider_value_long)) {
|
||||
slider_value = SLIDER_SCALE_10(slider_value_long);
|
||||
if (slider_value >= angle_slider->GetMin() && slider_value <= angle_slider->GetMax()) {
|
||||
|
@ -149,11 +163,25 @@ StepMeshDialog::StepMeshDialog(wxWindow* parent, fs::path file)
|
|||
}
|
||||
}));
|
||||
|
||||
angle_slider->Bind(wxEVT_SLIDER, ([this, angle_slider, angle_input](wxCommandEvent& e) {
|
||||
double slider_value = SLIDER_UNSCALE_10(angle_slider->GetValue());
|
||||
angle_input->GetTextCtrl()->SetValue(wxString::Format("%.2f", slider_value));
|
||||
m_angle_last = wxString::Format("%.2f", slider_value);
|
||||
}));
|
||||
angle_slider->Bind(wxEVT_LEFT_UP, ([this](wxMouseEvent& e) {
|
||||
update_mesh_number_text();
|
||||
e.Skip();
|
||||
}));
|
||||
|
||||
bSizer->Add(angle_sizer, 1, wxEXPAND | wxLEFT | wxRIGHT, LEFT_RIGHT_PADING);
|
||||
|
||||
|
||||
mesh_face_number_text = new wxStaticText(this, wxID_ANY, _L("Number of generated surfaces: 0"));
|
||||
bSizer->Add(mesh_face_number_text, 1, wxEXPAND | wxLEFT | wxRIGHT, LEFT_RIGHT_PADING);
|
||||
wxBoxSizer* mesh_face_number_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxStaticText* mesh_face_number_title = new wxStaticText(this, wxID_ANY, _L("Number of triangular facets: "));
|
||||
mesh_face_number_text = new wxStaticText(this, wxID_ANY, _L("0"));
|
||||
mesh_face_number_text->SetMinSize(wxSize(FromDIP(150), -1));
|
||||
mesh_face_number_sizer->Add(mesh_face_number_title, 0, wxALIGN_LEFT);
|
||||
mesh_face_number_sizer->Add(mesh_face_number_text, 0, wxALIGN_LEFT);
|
||||
bSizer->Add(mesh_face_number_sizer, 1, wxEXPAND | wxLEFT | wxRIGHT, LEFT_RIGHT_PADING);
|
||||
|
||||
wxBoxSizer* bSizer_button = new wxBoxSizer(wxHORIZONTAL);
|
||||
bSizer_button->SetMinSize(wxSize(FromDIP(100), -1));
|
||||
|
@ -170,7 +198,14 @@ StepMeshDialog::StepMeshDialog(wxWindow* parent, fs::path file)
|
|||
m_button_ok->SetCornerRadius(FromDIP(12));
|
||||
bSizer_button->Add(m_button_ok, 0, wxALIGN_RIGHT, BUTTON_BORDER);
|
||||
|
||||
m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { EndModal(wxID_OK); });
|
||||
m_button_ok->Bind(wxEVT_LEFT_DOWN, [this, angle_input, linear_input](wxMouseEvent& e) {
|
||||
stop_task();
|
||||
if (validate_number_range(angle_input->GetTextCtrl()->GetValue(), 0.01, 1) &&
|
||||
validate_number_range(linear_input->GetTextCtrl()->GetValue(), 0.001, 0.1)) {
|
||||
EndModal(wxID_OK);
|
||||
}
|
||||
SetFocusIgnoringChildren();
|
||||
});
|
||||
|
||||
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
|
||||
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
|
||||
|
@ -184,7 +219,10 @@ StepMeshDialog::StepMeshDialog(wxWindow* parent, fs::path file)
|
|||
m_button_cancel->SetCornerRadius(FromDIP(12));
|
||||
bSizer_button->Add(m_button_cancel, 0, wxALIGN_RIGHT | wxLEFT, BUTTON_BORDER);
|
||||
|
||||
m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) { EndModal(wxID_CANCEL); });
|
||||
m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
stop_task();
|
||||
EndModal(wxID_CANCEL);
|
||||
});
|
||||
|
||||
bSizer->Add(bSizer_button, 0, wxALIGN_RIGHT | wxRIGHT| wxBOTTOM, LEFT_RIGHT_PADING);
|
||||
|
||||
|
@ -193,24 +231,57 @@ StepMeshDialog::StepMeshDialog(wxWindow* parent, fs::path file)
|
|||
this->Layout();
|
||||
bSizer->Fit(this);
|
||||
|
||||
this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) { });
|
||||
this->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
|
||||
SetFocusIgnoringChildren();
|
||||
});
|
||||
mesh_face_number_text->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
|
||||
SetFocusIgnoringChildren();
|
||||
});
|
||||
|
||||
this->Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& e) {
|
||||
stop_task();
|
||||
EndModal(wxID_CANCEL);
|
||||
});
|
||||
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
}
|
||||
|
||||
long StepMeshDialog::get_mesh_number()
|
||||
void StepMeshDialog::on_task_done(wxCommandEvent& event)
|
||||
{
|
||||
Model model;
|
||||
long number = 0;
|
||||
const std::string file_path = m_file.string();
|
||||
bool is_cb_cancel = false;
|
||||
bool result = load_step(file_path.c_str(), &model, is_cb_cancel, get_linear_defletion(), get_angle_defletion(), nullptr, nullptr, number);
|
||||
return number;
|
||||
wxString text = event.GetString();
|
||||
mesh_face_number_text->SetLabel(text);
|
||||
if (task.valid()) {
|
||||
task.get();
|
||||
}
|
||||
}
|
||||
|
||||
void StepMeshDialog::stop_task()
|
||||
{
|
||||
if (task.valid()) {
|
||||
m_file.m_stop_mesh.store(true);
|
||||
unsigned int test = task.get();
|
||||
m_file.m_stop_mesh.store(false);
|
||||
std::cout << test << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void StepMeshDialog::update_mesh_number_text()
|
||||
{
|
||||
long number = get_mesh_number();
|
||||
wxString newText = wxString::Format("Number of generated surfaces: %d", number);
|
||||
if (m_last_linear == get_linear_defletion() && m_last_angle == get_angle_defletion())
|
||||
return;
|
||||
wxString newText = wxString::Format(_L("Calculating, please wait..."));
|
||||
mesh_face_number_text->SetLabel(newText);
|
||||
|
||||
stop_task();
|
||||
task = std::async(std::launch::async, [&] {
|
||||
unsigned int number = m_file.get_triangle_num(get_linear_defletion(), get_angle_defletion());
|
||||
if (number != 0) {
|
||||
wxString number_text = wxString::Format("%d", number);
|
||||
wxCommandEvent event(wxEVT_THREAD_DONE);
|
||||
event.SetString(number_text);
|
||||
wxPostEvent(this, event);
|
||||
}
|
||||
return number;
|
||||
});
|
||||
}
|
|
@ -1,15 +1,16 @@
|
|||
#ifndef _STEP_MESH_DIALOG_H_
|
||||
#define _STEP_MESH_DIALOG_H_
|
||||
|
||||
#include <thread>
|
||||
#include "GUI_Utils.hpp"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <wx/sizer.h>
|
||||
#include "libslic3r/Format/STEP.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
class Button;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
class StepMeshDialog : public Slic3r::GUI::DPIDialog
|
||||
{
|
||||
public:
|
||||
StepMeshDialog(wxWindow* parent, fs::path file);
|
||||
StepMeshDialog(wxWindow* parent, Slic3r::Step& file);
|
||||
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||
inline double get_linear_defletion() {
|
||||
double value;
|
||||
|
@ -27,16 +28,20 @@ public:
|
|||
return 0.5;
|
||||
}
|
||||
}
|
||||
long get_mesh_number();
|
||||
private:
|
||||
fs::path m_file;
|
||||
Slic3r::Step& m_file;
|
||||
Button* m_button_ok = nullptr;
|
||||
Button* m_button_cancel = nullptr;
|
||||
wxString m_linear_last = wxString::Format("%.3f", 0.003);
|
||||
wxString m_angle_last = wxString::Format("%.2f", 0.5);
|
||||
wxStaticText* mesh_face_number_text;
|
||||
double m_last_linear;
|
||||
double m_last_angle;
|
||||
std::future<unsigned int> task;
|
||||
bool validate_number_range(const wxString& value, double min, double max);
|
||||
void update_mesh_number_text();
|
||||
void on_task_done(wxCommandEvent& event);
|
||||
void stop_task();
|
||||
};
|
||||
|
||||
#endif // _STEP_MESH_DIALOG_H_
|
|
@ -6,6 +6,11 @@
|
|||
#define NOMINMAX
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
#include <CommCtrl.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#endif
|
||||
|
||||
#include <float.h>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue