mirror of
https://github.com/FULU-Foundation/OrcaSlicer-bambulab.git
synced 2026-09-12 13:48:08 +02:00
Merge branch 'dev2' into lm_sla_supports_ui
This commit is contained in:
@@ -196,7 +196,11 @@ const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f };
|
||||
|
||||
GLVolume::GLVolume(float r, float g, float b, float a)
|
||||
: m_offset(Vec3d::Zero())
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
, m_rotation(Vec3d::Zero())
|
||||
#else
|
||||
, m_rotation(0.0)
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
, m_scaling_factor(1.0)
|
||||
, m_world_matrix(Transform3f::Identity())
|
||||
, m_world_matrix_dirty(true)
|
||||
@@ -255,7 +259,24 @@ void GLVolume::set_render_color()
|
||||
set_render_color(color, 4);
|
||||
}
|
||||
|
||||
double GLVolume::get_rotation()
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
const Vec3d& GLVolume::get_rotation() const
|
||||
{
|
||||
return m_rotation;
|
||||
}
|
||||
|
||||
void GLVolume::set_rotation(const Vec3d& rotation)
|
||||
{
|
||||
if (m_rotation != rotation)
|
||||
{
|
||||
m_rotation = rotation;
|
||||
m_world_matrix_dirty = true;
|
||||
m_transformed_bounding_box_dirty = true;
|
||||
m_transformed_convex_hull_bounding_box_dirty = true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
double GLVolume::get_rotation() const
|
||||
{
|
||||
return m_rotation;
|
||||
}
|
||||
@@ -270,6 +291,7 @@ void GLVolume::set_rotation(double rotation)
|
||||
m_transformed_convex_hull_bounding_box_dirty = true;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
const Vec3d& GLVolume::get_offset() const
|
||||
{
|
||||
@@ -327,7 +349,13 @@ const Transform3f& GLVolume::world_matrix() const
|
||||
{
|
||||
m_world_matrix = Transform3f::Identity();
|
||||
m_world_matrix.translate(m_offset.cast<float>());
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
m_world_matrix.rotate(Eigen::AngleAxisf((float)m_rotation(2), Vec3f::UnitZ()));
|
||||
m_world_matrix.rotate(Eigen::AngleAxisf((float)m_rotation(1), Vec3f::UnitY()));
|
||||
m_world_matrix.rotate(Eigen::AngleAxisf((float)m_rotation(0), Vec3f::UnitX()));
|
||||
#else
|
||||
m_world_matrix.rotate(Eigen::AngleAxisf((float)m_rotation, Vec3f::UnitZ()));
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
m_world_matrix.scale((float)m_scaling_factor);
|
||||
m_world_matrix_dirty = false;
|
||||
}
|
||||
@@ -403,7 +431,13 @@ void GLVolume::render() const
|
||||
::glCullFace(GL_BACK);
|
||||
::glPushMatrix();
|
||||
::glTranslated(m_offset(0), m_offset(1), m_offset(2));
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
::glRotated(m_rotation(2) * 180.0 / (double)PI, 0.0, 0.0, 1.0);
|
||||
::glRotated(m_rotation(1) * 180.0 / (double)PI, 0.0, 1.0, 0.0);
|
||||
::glRotated(m_rotation(0) * 180.0 / (double)PI, 1.0, 0.0, 0.0);
|
||||
#else
|
||||
::glRotated(m_rotation * 180.0 / (double)PI, 0.0, 0.0, 1.0);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
::glScaled(m_scaling_factor, m_scaling_factor, m_scaling_factor);
|
||||
if (this->indexed_vertex_array.indexed())
|
||||
this->indexed_vertex_array.render(this->tverts_range, this->qverts_range);
|
||||
@@ -529,7 +563,13 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
|
||||
|
||||
::glPushMatrix();
|
||||
::glTranslated(m_offset(0), m_offset(1), m_offset(2));
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
::glRotated(m_rotation(2) * 180.0 / (double)PI, 0.0, 0.0, 1.0);
|
||||
::glRotated(m_rotation(1) * 180.0 / (double)PI, 0.0, 1.0, 0.0);
|
||||
::glRotated(m_rotation(0) * 180.0 / (double)PI, 1.0, 0.0, 0.0);
|
||||
#else
|
||||
::glRotated(m_rotation * 180.0 / (double)PI, 0.0, 0.0, 1.0);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
::glScaled(m_scaling_factor, m_scaling_factor, m_scaling_factor);
|
||||
|
||||
if (n_triangles > 0)
|
||||
@@ -574,7 +614,13 @@ void GLVolume::render_legacy() const
|
||||
|
||||
::glPushMatrix();
|
||||
::glTranslated(m_offset(0), m_offset(1), m_offset(2));
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
::glRotated(m_rotation(2) * 180.0 / (double)PI, 0.0, 0.0, 1.0);
|
||||
::glRotated(m_rotation(1) * 180.0 / (double)PI, 0.0, 1.0, 0.0);
|
||||
::glRotated(m_rotation(0) * 180.0 / (double)PI, 1.0, 0.0, 0.0);
|
||||
#else
|
||||
::glRotated(m_rotation * 180.0 / (double)PI, 0.0, 0.0, 1.0);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
::glScaled(m_scaling_factor, m_scaling_factor, m_scaling_factor);
|
||||
|
||||
if (n_triangles > 0)
|
||||
@@ -591,7 +637,7 @@ double GLVolume::layer_height_texture_z_to_row_id() const
|
||||
return (this->layer_height_texture.get() == nullptr) ? 0.0 : double(this->layer_height_texture->cells - 1) / (double(this->layer_height_texture->width) * this->layer_height_texture_data.print_object->model_object()->bounding_box().max(2));
|
||||
}
|
||||
|
||||
void GLVolume::generate_layer_height_texture(PrintObject *print_object, bool force)
|
||||
void GLVolume::generate_layer_height_texture(const PrintObject *print_object, bool force)
|
||||
{
|
||||
LayersTexture *tex = this->layer_height_texture.get();
|
||||
if (tex == nullptr)
|
||||
@@ -599,7 +645,7 @@ void GLVolume::generate_layer_height_texture(PrintObject *print_object, bool for
|
||||
return;
|
||||
|
||||
// Always try to update the layer height profile.
|
||||
bool update = print_object->update_layer_height_profile(print_object->model_object()->layer_height_profile) || force;
|
||||
bool update = print_object->update_layer_height_profile(const_cast<ModelObject*>(print_object->model_object())->layer_height_profile) || force;
|
||||
// Update if the layer height profile was changed, or when the texture is not valid.
|
||||
if (! update && ! tex->data.empty() && tex->cells > 0)
|
||||
// Texture is valid, don't update.
|
||||
@@ -698,7 +744,11 @@ std::vector<int> GLVolumeCollection::load_object(
|
||||
#else
|
||||
v.set_offset(Vec3d(instance->offset(0), instance->offset(1), 0.0));
|
||||
#endif // ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
v.set_rotation(instance->get_rotation());
|
||||
#else
|
||||
v.set_rotation(instance->rotation);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
v.set_scaling_factor(instance->scaling_factor);
|
||||
}
|
||||
}
|
||||
@@ -1687,7 +1737,7 @@ void _3DScene::extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity,
|
||||
if (extrusion_entity_collection != nullptr)
|
||||
extrusionentity_to_verts(*extrusion_entity_collection, print_z, copy, volume);
|
||||
else {
|
||||
CONFESS("Unexpected extrusion_entity type in to_verts()");
|
||||
throw std::runtime_error("Unexpected extrusion_entity type in to_verts()");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2067,12 +2117,30 @@ void _3DScene::register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, vo
|
||||
|
||||
void _3DScene::register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
#if !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
s_canvas_mgr.register_on_gizmo_rotate_callback(canvas, callback);
|
||||
#endif // !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
}
|
||||
|
||||
void _3DScene::register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
s_canvas_mgr.register_on_gizmo_rotate_3D_callback(canvas, callback);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
}
|
||||
|
||||
void _3DScene::register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
#if !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
s_canvas_mgr.register_on_gizmo_flatten_callback(canvas, callback);
|
||||
#endif // !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
}
|
||||
|
||||
void _3DScene::register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
s_canvas_mgr.register_on_gizmo_flatten_3D_callback(canvas, callback);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
}
|
||||
|
||||
void _3DScene::register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback)
|
||||
|
||||
@@ -225,7 +225,7 @@ class GLVolume {
|
||||
// ID of the shader used to render with the layer height texture
|
||||
unsigned int shader_id;
|
||||
// The print object to update when generating the layer height texture
|
||||
PrintObject* print_object;
|
||||
const PrintObject* print_object;
|
||||
|
||||
float z_cursor_relative;
|
||||
float edit_band_width;
|
||||
@@ -256,8 +256,13 @@ public:
|
||||
private:
|
||||
// Offset of the volume to be rendered.
|
||||
Vec3d m_offset;
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
// Rotation around three axes of the volume to be rendered.
|
||||
Vec3d m_rotation;
|
||||
#else
|
||||
// Rotation around Z axis of the volume to be rendered.
|
||||
double m_rotation;
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
// Scale factor of the volume to be rendered.
|
||||
double m_scaling_factor;
|
||||
// World matrix of the volume to be rendered.
|
||||
@@ -327,8 +332,13 @@ public:
|
||||
// Sets render color in dependence of current state
|
||||
void set_render_color();
|
||||
|
||||
double get_rotation();
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
const Vec3d& get_rotation() const;
|
||||
void set_rotation(const Vec3d& rotation);
|
||||
#else
|
||||
double get_rotation() const;
|
||||
void set_rotation(double rotation);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
const Vec3d& get_offset() const;
|
||||
void set_offset(const Vec3d& offset);
|
||||
@@ -382,9 +392,9 @@ public:
|
||||
(void*)(layer_height_texture->data.data() + layer_height_texture->width * layer_height_texture->height * 4);
|
||||
}
|
||||
double layer_height_texture_z_to_row_id() const;
|
||||
void generate_layer_height_texture(PrintObject *print_object, bool force);
|
||||
void generate_layer_height_texture(const PrintObject *print_object, bool force);
|
||||
|
||||
void set_layer_height_texture_data(unsigned int texture_id, unsigned int shader_id, PrintObject* print_object, float z_cursor_relative, float edit_band_width)
|
||||
void set_layer_height_texture_data(unsigned int texture_id, unsigned int shader_id, const PrintObject* print_object, float z_cursor_relative, float edit_band_width)
|
||||
{
|
||||
layer_height_texture_data.texture_id = texture_id;
|
||||
layer_height_texture_data.shader_id = shader_id;
|
||||
@@ -558,7 +568,9 @@ public:
|
||||
static void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback);
|
||||
static void register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback);
|
||||
|
||||
static void register_action_add_callback(wxGLCanvas* canvas, void* callback);
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
#include "BackgroundSlicingProcess.hpp"
|
||||
#include "GUI.hpp"
|
||||
|
||||
#include <wx/event.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/stdpaths.h>
|
||||
|
||||
// Print now includes tbb, and tbb includes Windows. This breaks compilation of wxWidgets if included before wx.
|
||||
#include "../../libslic3r/Print.hpp"
|
||||
#include "../../libslic3r/Utils.hpp"
|
||||
#include "../../libslic3r/GCode/PostProcessor.hpp"
|
||||
|
||||
//#undef NDEBUG
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
extern wxPanel *g_wxPlater;
|
||||
};
|
||||
|
||||
BackgroundSlicingProcess::BackgroundSlicingProcess()
|
||||
{
|
||||
m_temp_output_path = wxStandardPaths::Get().GetTempDir().utf8_str().data();
|
||||
m_temp_output_path += (boost::format(".%1%.gcode") % get_current_pid()).str();
|
||||
}
|
||||
|
||||
BackgroundSlicingProcess::~BackgroundSlicingProcess()
|
||||
{
|
||||
this->stop();
|
||||
this->join_background_thread();
|
||||
boost::nowide::remove(m_temp_output_path.c_str());
|
||||
}
|
||||
|
||||
void BackgroundSlicingProcess::thread_proc()
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(m_mutex);
|
||||
// Let the caller know we are ready to run the background processing task.
|
||||
m_state = STATE_IDLE;
|
||||
lck.unlock();
|
||||
m_condition.notify_one();
|
||||
for (;;) {
|
||||
assert(m_state == STATE_IDLE || m_state == STATE_CANCELED || m_state == STATE_FINISHED);
|
||||
// Wait until a new task is ready to be executed, or this thread should be finished.
|
||||
lck.lock();
|
||||
m_condition.wait(lck, [this](){ return m_state == STATE_STARTED || m_state == STATE_EXIT; });
|
||||
if (m_state == STATE_EXIT)
|
||||
// Exiting this thread.
|
||||
break;
|
||||
// Process the background slicing task.
|
||||
m_state = STATE_RUNNING;
|
||||
lck.unlock();
|
||||
std::string error;
|
||||
try {
|
||||
assert(m_print != nullptr);
|
||||
m_print->process();
|
||||
if (! m_print->canceled()) {
|
||||
wxQueueEvent(GUI::g_wxPlater, new wxCommandEvent(m_event_sliced_id));
|
||||
m_print->export_gcode(m_temp_output_path, m_gcode_preview_data);
|
||||
if (! m_print->canceled() && ! m_output_path.empty()) {
|
||||
if (copy_file(m_temp_output_path, m_output_path) != 0)
|
||||
throw std::runtime_error("Copying of the temporary G-code to the output G-code failed");
|
||||
m_print->set_status(95, "Running post-processing scripts");
|
||||
run_post_process_scripts(m_output_path, m_print->config());
|
||||
}
|
||||
}
|
||||
} catch (CanceledException &ex) {
|
||||
// Canceled, this is all right.
|
||||
assert(m_print->canceled());
|
||||
} catch (std::exception &ex) {
|
||||
error = ex.what();
|
||||
} catch (...) {
|
||||
error = "Unknown C++ exception.";
|
||||
}
|
||||
lck.lock();
|
||||
m_state = m_print->canceled() ? STATE_CANCELED : STATE_FINISHED;
|
||||
wxCommandEvent evt(m_event_finished_id);
|
||||
evt.SetString(error);
|
||||
evt.SetInt(m_print->canceled() ? -1 : (error.empty() ? 1 : 0));
|
||||
wxQueueEvent(GUI::g_wxPlater, evt.Clone());
|
||||
m_print->restart();
|
||||
lck.unlock();
|
||||
// Let the UI thread wake up if it is waiting for the background task to finish.
|
||||
m_condition.notify_one();
|
||||
// Let the UI thread see the result.
|
||||
}
|
||||
m_state = STATE_EXITED;
|
||||
lck.unlock();
|
||||
// End of the background processing thread. The UI thread should join m_thread now.
|
||||
}
|
||||
|
||||
void BackgroundSlicingProcess::join_background_thread()
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(m_mutex);
|
||||
if (m_state == STATE_INITIAL) {
|
||||
// Worker thread has not been started yet.
|
||||
assert(! m_thread.joinable());
|
||||
} else {
|
||||
assert(m_state == STATE_IDLE);
|
||||
assert(m_thread.joinable());
|
||||
// Notify the worker thread to exit.
|
||||
m_state = STATE_EXIT;
|
||||
lck.unlock();
|
||||
m_condition.notify_one();
|
||||
// Wait until the worker thread exits.
|
||||
m_thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
bool BackgroundSlicingProcess::start()
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(m_mutex);
|
||||
if (m_state == STATE_INITIAL) {
|
||||
// The worker thread is not running yet. Start it.
|
||||
assert(! m_thread.joinable());
|
||||
m_thread = std::thread([this]{this->thread_proc();});
|
||||
// Wait until the worker thread is ready to execute the background processing task.
|
||||
m_condition.wait(lck, [this](){ return m_state == STATE_IDLE; });
|
||||
}
|
||||
assert(m_state == STATE_IDLE || this->running());
|
||||
if (this->running())
|
||||
// The background processing thread is already running.
|
||||
return false;
|
||||
if (! this->idle())
|
||||
throw std::runtime_error("Cannot start a background task, the worker thread is not idle.");
|
||||
m_state = STATE_STARTED;
|
||||
lck.unlock();
|
||||
m_condition.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BackgroundSlicingProcess::stop()
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(m_mutex);
|
||||
if (m_state == STATE_INITIAL) {
|
||||
this->m_output_path.clear();
|
||||
return false;
|
||||
}
|
||||
assert(this->running());
|
||||
if (m_state == STATE_STARTED || m_state == STATE_RUNNING) {
|
||||
m_print->cancel();
|
||||
// Wait until the background processing stops by being canceled.
|
||||
m_condition.wait(lck, [this](){ return m_state == STATE_CANCELED; });
|
||||
// In the "Canceled" state. Reset the state to "Idle".
|
||||
m_state = STATE_IDLE;
|
||||
} else if (m_state == STATE_FINISHED || m_state == STATE_CANCELED) {
|
||||
// In the "Finished" or "Canceled" state. Reset the state to "Idle".
|
||||
m_state = STATE_IDLE;
|
||||
}
|
||||
this->m_output_path.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Apply config over the print. Returns false, if the new config values caused any of the already
|
||||
// processed steps to be invalidated, therefore the task will need to be restarted.
|
||||
bool BackgroundSlicingProcess::apply_config(const DynamicPrintConfig &config)
|
||||
{
|
||||
this->stop();
|
||||
bool invalidated = m_print->apply_config(config);
|
||||
return invalidated;
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef slic3r_GUI_BackgroundSlicingProcess_hpp_
|
||||
#define slic3r_GUI_BackgroundSlicingProcess_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class DynamicPrintConfig;
|
||||
class GCodePreviewData;
|
||||
class Print;
|
||||
|
||||
// Support for the GUI background processing (Slicing and G-code generation).
|
||||
// As of now this class is not declared in Slic3r::GUI due to the Perl bindings limits.
|
||||
class BackgroundSlicingProcess
|
||||
{
|
||||
public:
|
||||
BackgroundSlicingProcess();
|
||||
// Stop the background processing and finalize the bacgkround processing thread, remove temp files.
|
||||
~BackgroundSlicingProcess();
|
||||
|
||||
void set_print(Print *print) { m_print = print; }
|
||||
void set_gcode_preview_data(GCodePreviewData *gpd) { m_gcode_preview_data = gpd; }
|
||||
// The following wxCommandEvent will be sent to the UI thread / Platter window, when the slicing is finished
|
||||
// and the background processing will transition into G-code export.
|
||||
// The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed.
|
||||
void set_sliced_event(int event_id) { m_event_sliced_id = event_id; }
|
||||
// The following wxCommandEvent will be sent to the UI thread / Platter window, when the G-code export is finished.
|
||||
// The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed.
|
||||
void set_finished_event(int event_id) { m_event_finished_id = event_id; }
|
||||
|
||||
// Set the output path of the G-code.
|
||||
void set_output_path(const std::string &path) { m_output_path = path; }
|
||||
// Start the background processing. Returns false if the background processing was already running.
|
||||
bool start();
|
||||
// Cancel the background processing. Returns false if the background processing was not running.
|
||||
// A stopped background processing may be restarted with start().
|
||||
bool stop();
|
||||
|
||||
// Apply config over the print. Returns false, if the new config values caused any of the already
|
||||
// processed steps to be invalidated, therefore the task will need to be restarted.
|
||||
bool apply_config(const DynamicPrintConfig &config);
|
||||
|
||||
enum State {
|
||||
// m_thread is not running yet, or it did not reach the STATE_IDLE yet (it does not wait on the condition yet).
|
||||
STATE_INITIAL = 0,
|
||||
// m_thread is waiting for the task to execute.
|
||||
STATE_IDLE,
|
||||
STATE_STARTED,
|
||||
// m_thread is executing a task.
|
||||
STATE_RUNNING,
|
||||
// m_thread finished executing a task, and it is waiting until the UI thread picks up the results.
|
||||
STATE_FINISHED,
|
||||
// m_thread finished executing a task, the task has been canceled by the UI thread, therefore the UI thread will not be notified.
|
||||
STATE_CANCELED,
|
||||
// m_thread exited the loop and it is going to finish. The UI thread should join on m_thread.
|
||||
STATE_EXIT,
|
||||
STATE_EXITED,
|
||||
};
|
||||
State state() const { return m_state; }
|
||||
bool idle() const { return m_state == STATE_IDLE; }
|
||||
bool running() const { return m_state == STATE_STARTED || m_state == STATE_RUNNING || m_state == STATE_FINISHED || m_state == STATE_CANCELED; }
|
||||
|
||||
private:
|
||||
void thread_proc();
|
||||
void join_background_thread();
|
||||
|
||||
Print *m_print = nullptr;
|
||||
// Data structure, to which the G-code export writes its annotations.
|
||||
GCodePreviewData *m_gcode_preview_data = nullptr;
|
||||
std::string m_temp_output_path;
|
||||
std::string m_output_path;
|
||||
// Thread, on which the background processing is executed. The thread will always be present
|
||||
// and ready to execute the slicing process.
|
||||
std::thread m_thread;
|
||||
// Mutex and condition variable to synchronize m_thread with the UI thread.
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_condition;
|
||||
State m_state = STATE_INITIAL;
|
||||
|
||||
// wxWidgets command ID to be sent to the platter to inform that the slicing is finished, and the G-code export will continue.
|
||||
int m_event_sliced_id = 0;
|
||||
// wxWidgets command ID to be sent to the platter to inform that the task finished.
|
||||
int m_event_finished_id = 0;
|
||||
};
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
#endif /* slic3r_GUI_BackgroundSlicingProcess_hpp_ */
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "../../slic3r/GUI/GLGizmo.hpp"
|
||||
#include "../../libslic3r/ClipperUtils.hpp"
|
||||
#include "../../libslic3r/PrintConfig.hpp"
|
||||
#include "../../libslic3r/Print.hpp"
|
||||
#include "../../libslic3r/GCode/PreviewData.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
@@ -21,6 +20,9 @@
|
||||
#include <wx/image.h>
|
||||
#include <wx/settings.h>
|
||||
|
||||
// Print now includes tbb, and tbb includes Windows. This breaks compilation of wxWidgets if included before wx.
|
||||
#include "../../libslic3r/Print.hpp"
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
#include <tbb/spin_mutex.h>
|
||||
|
||||
@@ -1031,7 +1033,7 @@ void GLCanvas3D::LayersEditing::_render_profile(const PrintObject& print_object,
|
||||
// Get a maximum layer height value.
|
||||
// FIXME This is a duplicate code of Slicing.cpp.
|
||||
double layer_height_max = DBL_MAX;
|
||||
const PrintConfig& print_config = print_object.print()->config;
|
||||
const PrintConfig& print_config = print_object.print()->config();
|
||||
const std::vector<double>& nozzle_diameters = dynamic_cast<const ConfigOptionFloats*>(print_config.option("nozzle_diameter"))->values;
|
||||
const std::vector<double>& layer_heights_min = dynamic_cast<const ConfigOptionFloats*>(print_config.option("min_layer_height"))->values;
|
||||
const std::vector<double>& layer_heights_max = dynamic_cast<const ConfigOptionFloats*>(print_config.option("max_layer_height"))->values;
|
||||
@@ -1046,7 +1048,7 @@ void GLCanvas3D::LayersEditing::_render_profile(const PrintObject& print_object,
|
||||
layer_height_max *= 1.12;
|
||||
|
||||
double max_z = unscale<double>(print_object.size(2));
|
||||
double layer_height = dynamic_cast<const ConfigOptionFloat*>(print_object.config.option("layer_height"))->value;
|
||||
double layer_height = dynamic_cast<const ConfigOptionFloat*>(print_object.config().option("layer_height"))->value;
|
||||
float l = bar_rect.get_left();
|
||||
float w = bar_rect.get_right() - l;
|
||||
float b = bar_rect.get_bottom();
|
||||
@@ -1095,6 +1097,9 @@ GLCanvas3D::Mouse::Drag::Drag()
|
||||
GLCanvas3D::Mouse::Mouse()
|
||||
: dragging(false)
|
||||
, position(DBL_MAX, DBL_MAX)
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
, ignore_up_event(false)
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1181,9 +1186,11 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent)
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
// temporary disable x and y grabbers
|
||||
gizmo->disable_grabber(0);
|
||||
gizmo->disable_grabber(1);
|
||||
#endif // !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo));
|
||||
|
||||
@@ -1360,6 +1367,18 @@ void GLCanvas3D::Gizmos::update(const Linef3& mouse_ray, const Point* mouse_pos)
|
||||
curr->update(mouse_ray, mouse_pos);
|
||||
}
|
||||
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
void GLCanvas3D::Gizmos::process_double_click()
|
||||
{
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
GLGizmoBase* curr = _get_current();
|
||||
if (curr != nullptr)
|
||||
curr->process_double_click();
|
||||
}
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
|
||||
GLCanvas3D::Gizmos::EType GLCanvas3D::Gizmos::get_current_type() const
|
||||
{
|
||||
return m_current;
|
||||
@@ -1432,6 +1451,35 @@ void GLCanvas3D::Gizmos::set_scale(float scale)
|
||||
reinterpret_cast<GLGizmoScale3D*>(it->second)->set_scale(scale);
|
||||
}
|
||||
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
Vec3d GLCanvas3D::Gizmos::get_rotation() const
|
||||
{
|
||||
if (!m_enabled)
|
||||
return Vec3d::Zero();
|
||||
|
||||
GizmosMap::const_iterator it = m_gizmos.find(Rotate);
|
||||
return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoRotate3D*>(it->second)->get_rotation() : Vec3d::Zero();
|
||||
}
|
||||
|
||||
void GLCanvas3D::Gizmos::set_rotation(const Vec3d& rotation)
|
||||
{
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
GizmosMap::const_iterator it = m_gizmos.find(Rotate);
|
||||
if (it != m_gizmos.end())
|
||||
reinterpret_cast<GLGizmoRotate3D*>(it->second)->set_rotation(rotation);
|
||||
}
|
||||
|
||||
Vec3d GLCanvas3D::Gizmos::get_flattening_rotation() const
|
||||
{
|
||||
if (!m_enabled)
|
||||
return Vec3d::Zero();
|
||||
|
||||
GizmosMap::const_iterator it = m_gizmos.find(Flatten);
|
||||
return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoFlatten*>(it->second)->get_flattening_rotation() : Vec3d::Zero();
|
||||
}
|
||||
#else
|
||||
float GLCanvas3D::Gizmos::get_angle_z() const
|
||||
{
|
||||
if (!m_enabled)
|
||||
@@ -1459,6 +1507,7 @@ Vec3d GLCanvas3D::Gizmos::get_flattening_normal() const
|
||||
GizmosMap::const_iterator it = m_gizmos.find(Flatten);
|
||||
return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoFlatten*>(it->second)->get_flattening_normal() : Vec3d::Zero();
|
||||
}
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
void GLCanvas3D::Gizmos::set_flattening_data(const ModelObject* model_object)
|
||||
{
|
||||
@@ -1619,7 +1668,7 @@ bool GLCanvas3D::WarningTexture::generate(const std::string& msg)
|
||||
wxCoord w, h;
|
||||
memDC.GetTextExtent(msg, &w, &h);
|
||||
|
||||
int pow_of_two_size = next_highest_power_of_2((int)std::max(w, h));
|
||||
int pow_of_two_size = next_highest_power_of_2(std::max<unsigned int>(w, h));
|
||||
|
||||
m_original_width = (int)w;
|
||||
m_original_height = (int)h;
|
||||
@@ -2428,7 +2477,11 @@ void GLCanvas3D::update_gizmos_data()
|
||||
m_gizmos.set_position(Vec3d(model_instance->offset(0), model_instance->offset(1), 0.0));
|
||||
#endif // ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
m_gizmos.set_scale(model_instance->scaling_factor);
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
m_gizmos.set_rotation(model_instance->get_rotation());
|
||||
#else
|
||||
m_gizmos.set_angle_z(model_instance->rotation);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
m_gizmos.set_flattening_data(model_object);
|
||||
m_gizmos.set_model_object_ptr(model_object);
|
||||
}
|
||||
@@ -2438,7 +2491,11 @@ void GLCanvas3D::update_gizmos_data()
|
||||
{
|
||||
m_gizmos.set_position(Vec3d::Zero());
|
||||
m_gizmos.set_scale(1.0f);
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
m_gizmos.set_rotation(Vec3d::Zero());
|
||||
#else
|
||||
m_gizmos.set_angle_z(0.0f);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
m_gizmos.set_flattening_data(nullptr);
|
||||
}
|
||||
}
|
||||
@@ -2626,11 +2683,11 @@ void GLCanvas3D::reload_scene(bool force)
|
||||
float a = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_rotation_angle"))->value;
|
||||
|
||||
float depth = m_print->get_wipe_tower_depth();
|
||||
if (!m_print->state.is_done(psWipeTower))
|
||||
if (!m_print->is_step_done(psWipeTower))
|
||||
depth = (900.f/w) * (float)(extruders_count - 1) ;
|
||||
|
||||
m_volumes.load_wipe_tower_preview(1000, x, y, w, depth, (float)height, a, m_use_VBOs && m_initialized, !m_print->state.is_done(psWipeTower),
|
||||
m_print->config.nozzle_diameter.values[0] * 1.25f * 4.5f);
|
||||
m_volumes.load_wipe_tower_preview(1000, x, y, w, depth, (float)height, a, m_use_VBOs && m_initialized, !m_print->is_step_done(psWipeTower),
|
||||
m_print->config().nozzle_diameter.values[0] * 1.25f * 4.5f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2710,7 +2767,7 @@ void GLCanvas3D::load_preview(const std::vector<std::string>& str_tool_colors)
|
||||
|
||||
_load_print_toolpaths();
|
||||
_load_wipe_tower_toolpaths(str_tool_colors);
|
||||
for (const PrintObject* object : m_print->objects)
|
||||
for (const PrintObject* object : m_print->objects())
|
||||
{
|
||||
if (object != nullptr)
|
||||
_load_print_object_toolpaths(*object, str_tool_colors);
|
||||
@@ -2822,6 +2879,19 @@ void GLCanvas3D::register_on_gizmo_scale_uniformly_callback(void* callback)
|
||||
m_on_gizmo_scale_uniformly_callback.register_callback(callback);
|
||||
}
|
||||
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
void GLCanvas3D::register_on_gizmo_rotate_3D_callback(void* callback)
|
||||
{
|
||||
if (callback != nullptr)
|
||||
m_on_gizmo_rotate_3D_callback.register_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3D::register_on_gizmo_flatten_3D_callback(void* callback)
|
||||
{
|
||||
if (callback != nullptr)
|
||||
m_on_gizmo_flatten_3D_callback.register_callback(callback);
|
||||
}
|
||||
#else
|
||||
void GLCanvas3D::register_on_gizmo_rotate_callback(void* callback)
|
||||
{
|
||||
if (callback != nullptr)
|
||||
@@ -2833,6 +2903,7 @@ void GLCanvas3D::register_on_gizmo_flatten_callback(void* callback)
|
||||
if (callback != nullptr)
|
||||
m_on_gizmo_flatten_callback.register_callback(callback);
|
||||
}
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
void GLCanvas3D::register_on_update_geometry_info_callback(void* callback)
|
||||
{
|
||||
@@ -3108,6 +3179,41 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
m_toolbar_action_running = true;
|
||||
m_toolbar.do_action((unsigned int)toolbar_contains_mouse);
|
||||
}
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
else if (evt.LeftDClick() && m_gizmos.grabber_contains_mouse())
|
||||
{
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
m_mouse.ignore_up_event = true;
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
m_gizmos.process_double_click();
|
||||
switch (m_gizmos.get_current_type())
|
||||
{
|
||||
case Gizmos::Scale:
|
||||
{
|
||||
m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale());
|
||||
update_scale_values();
|
||||
m_dirty = true;
|
||||
break;
|
||||
}
|
||||
case Gizmos::Rotate:
|
||||
{
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
const Vec3d& rotation = m_gizmos.get_rotation();
|
||||
m_on_gizmo_rotate_3D_callback.call(rotation(0), rotation(1), rotation(2));
|
||||
#else
|
||||
m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z());
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
update_rotation_values();
|
||||
m_dirty = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
else if (evt.LeftDown() || evt.RightDown())
|
||||
{
|
||||
// If user pressed left or right button we first check whether this happened
|
||||
@@ -3126,7 +3232,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
if (evt.LeftDown())
|
||||
{
|
||||
// A volume is selected and the mouse is inside the reset button.
|
||||
m_print->get_object(layer_editing_object_idx)->reset_layer_height_profile();
|
||||
// The PrintObject::adjust_layer_height_profile() call adjusts the profile of its associated ModelObject, it does not modify the profile of the PrintObject itself,
|
||||
// therefore it is safe to call it while the background processing is running.
|
||||
const_cast<PrintObject*>(m_print->get_object(layer_editing_object_idx))->reset_layer_height_profile();
|
||||
// Index 2 means no editing, just wait for mouse up event.
|
||||
m_layers_editing.state = LayersEditing::Completed;
|
||||
|
||||
@@ -3155,6 +3263,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
m_mouse.drag.gizmo_volume_idx = _get_first_selected_volume_id(selected_object_idx);
|
||||
|
||||
if (m_gizmos.get_current_type() == Gizmos::Flatten) {
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
// Rotate the object so the normal points downward:
|
||||
const Vec3d& rotation = m_gizmos.get_flattening_rotation();
|
||||
m_on_gizmo_flatten_3D_callback.call(rotation(0), rotation(1), rotation(2));
|
||||
#else
|
||||
// Rotate the object so the normal points downward:
|
||||
Vec3d normal = m_gizmos.get_flattening_normal();
|
||||
if (normal(0) != 0.0 || normal(1) != 0.0 || normal(2) != 0.0) {
|
||||
@@ -3162,6 +3275,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
float angle = acos(clamp(-1.0, 1.0, -normal(2)));
|
||||
m_on_gizmo_flatten_callback.call(angle, (float)axis(0), (float)axis(1), (float)axis(2));
|
||||
}
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
}
|
||||
|
||||
m_dirty = true;
|
||||
@@ -3348,6 +3462,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
case Gizmos::Rotate:
|
||||
{
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
// Apply new temporary rotation
|
||||
Vec3d rotation = m_gizmos.get_rotation();
|
||||
for (GLVolume* v : volumes)
|
||||
{
|
||||
v->set_rotation(rotation);
|
||||
}
|
||||
update_rotation_value(rotation);
|
||||
#else
|
||||
// Apply new temporary angle_z
|
||||
float angle_z = m_gizmos.get_angle_z();
|
||||
for (GLVolume* v : volumes)
|
||||
@@ -3355,6 +3478,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
v->set_rotation((double)angle_z);
|
||||
}
|
||||
update_rotation_value((double)angle_z, Z);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -3463,12 +3587,20 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging() && !is_layers_editing_enabled())
|
||||
{
|
||||
// deselect and propagate event through callback
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
if (!m_mouse.ignore_up_event && m_picking_enabled && !m_toolbar_action_running)
|
||||
#else
|
||||
if (m_picking_enabled && !m_toolbar_action_running)
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
{
|
||||
deselect_volumes();
|
||||
_on_select(-1, -1);
|
||||
update_gizmos_data();
|
||||
}
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
else if (m_mouse.ignore_up_event)
|
||||
m_mouse.ignore_up_event = false;
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
}
|
||||
else if (evt.LeftUp() && m_gizmos.is_dragging())
|
||||
{
|
||||
@@ -3502,14 +3634,19 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
}
|
||||
case Gizmos::Rotate:
|
||||
{
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
const Vec3d& rotation = m_gizmos.get_rotation();
|
||||
m_on_gizmo_rotate_3D_callback.call(rotation(0), rotation(1), rotation(2));
|
||||
#else
|
||||
m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z());
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_gizmos.stop_dragging();
|
||||
Slic3r::GUI::update_settings_value();
|
||||
update_settings_value();
|
||||
}
|
||||
|
||||
m_mouse.drag.move_volume_idx = -1;
|
||||
@@ -3949,8 +4086,13 @@ void GLCanvas3D::_deregister_callbacks()
|
||||
m_on_wipe_tower_moved_callback.deregister_callback();
|
||||
m_on_enable_action_buttons_callback.deregister_callback();
|
||||
m_on_gizmo_scale_uniformly_callback.deregister_callback();
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
m_on_gizmo_rotate_3D_callback.deregister_callback();
|
||||
m_on_gizmo_flatten_3D_callback.deregister_callback();
|
||||
#else
|
||||
m_on_gizmo_rotate_callback.deregister_callback();
|
||||
m_on_gizmo_flatten_callback.deregister_callback();
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
m_on_update_geometry_info_callback.deregister_callback();
|
||||
|
||||
m_action_add_callback.deregister_callback();
|
||||
@@ -3977,7 +4119,7 @@ void GLCanvas3D::_mark_volumes_for_layer_height() const
|
||||
int shader_id = m_layers_editing.get_shader_program_id();
|
||||
|
||||
if (is_layers_editing_enabled() && (shader_id != -1) && vol->selected &&
|
||||
vol->has_layer_height_texture() && (object_id < (int)m_print->objects.size()))
|
||||
vol->has_layer_height_texture() && (object_id < (int)m_print->objects().size()))
|
||||
{
|
||||
vol->set_layer_height_texture_data(m_layers_editing.get_z_texture_id(), shader_id,
|
||||
m_print->get_object(object_id), _get_layers_editing_cursor_z_relative(), m_layers_editing.band_width);
|
||||
@@ -4215,7 +4357,7 @@ void GLCanvas3D::_render_layer_editing_overlay() const
|
||||
// If the active object was not allocated at the Print, go away.This should only be a momentary case between an object addition / deletion
|
||||
// and an update by Platter::async_apply_config.
|
||||
int object_idx = int(volume->select_group_id / 1000000);
|
||||
if ((int)m_print->objects.size() < object_idx)
|
||||
if ((int)m_print->objects().size() < object_idx)
|
||||
return;
|
||||
|
||||
const PrintObject* print_object = m_print->get_object(object_idx);
|
||||
@@ -4302,7 +4444,7 @@ void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt)
|
||||
if (m_print == nullptr)
|
||||
return;
|
||||
|
||||
PrintObject* selected_obj = m_print->get_object(object_idx_selected);
|
||||
const PrintObject* selected_obj = m_print->get_object(object_idx_selected);
|
||||
if (selected_obj == nullptr)
|
||||
return;
|
||||
|
||||
@@ -4317,14 +4459,15 @@ void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt)
|
||||
|
||||
// Mark the volume as modified, so Print will pick its layer height profile ? Where to mark it ?
|
||||
// Start a timer to refresh the print ? schedule_background_process() ?
|
||||
// The PrintObject::adjust_layer_height_profile() call adjusts the profile of its associated ModelObject, it does not modify the profile of the PrintObject itself.
|
||||
selected_obj->adjust_layer_height_profile(m_layers_editing.last_z, m_layers_editing.strength, m_layers_editing.band_width, m_layers_editing.last_action);
|
||||
// The PrintObject::adjust_layer_height_profile() call adjusts the profile of its associated ModelObject, it does not modify the profile of the PrintObject itself,
|
||||
// therefore it is safe to call it while the background processing is running.
|
||||
const_cast<PrintObject*>(selected_obj)->adjust_layer_height_profile(m_layers_editing.last_z, m_layers_editing.strength, m_layers_editing.band_width, m_layers_editing.last_action);
|
||||
|
||||
// searches the id of the first volume of the selected object
|
||||
int volume_idx = 0;
|
||||
for (int i = 0; i < object_idx_selected; ++i)
|
||||
{
|
||||
PrintObject* obj = m_print->get_object(i);
|
||||
const PrintObject* obj = m_print->get_object(i);
|
||||
if (obj != nullptr)
|
||||
{
|
||||
for (int j = 0; j < (int)obj->region_volumes.size(); ++j)
|
||||
@@ -4395,7 +4538,7 @@ int GLCanvas3D::_get_first_selected_object_id() const
|
||||
{
|
||||
if (m_print != nullptr)
|
||||
{
|
||||
int objects_count = (int)m_print->objects.size();
|
||||
int objects_count = (int)m_print->objects().size();
|
||||
|
||||
for (const GLVolume* vol : m_volumes.volumes)
|
||||
{
|
||||
@@ -4434,36 +4577,36 @@ void GLCanvas3D::_load_print_toolpaths()
|
||||
if (m_print == nullptr)
|
||||
return;
|
||||
|
||||
if (!m_print->state.is_done(psSkirt) || !m_print->state.is_done(psBrim))
|
||||
if (!m_print->is_step_done(psSkirt) || !m_print->is_step_done(psBrim))
|
||||
return;
|
||||
|
||||
if (!m_print->has_skirt() && (m_print->config.brim_width.value == 0))
|
||||
if (!m_print->has_skirt() && (m_print->config().brim_width.value == 0))
|
||||
return;
|
||||
|
||||
const float color[] = { 0.5f, 1.0f, 0.5f, 1.0f }; // greenish
|
||||
|
||||
// number of skirt layers
|
||||
size_t total_layer_count = 0;
|
||||
for (const PrintObject* print_object : m_print->objects)
|
||||
for (const PrintObject* print_object : m_print->objects())
|
||||
{
|
||||
total_layer_count = std::max(total_layer_count, print_object->total_layer_count());
|
||||
}
|
||||
size_t skirt_height = m_print->has_infinite_skirt() ? total_layer_count : std::min<size_t>(m_print->config.skirt_height.value, total_layer_count);
|
||||
if ((skirt_height == 0) && (m_print->config.brim_width.value > 0))
|
||||
size_t skirt_height = m_print->has_infinite_skirt() ? total_layer_count : std::min<size_t>(m_print->config().skirt_height.value, total_layer_count);
|
||||
if ((skirt_height == 0) && (m_print->config().brim_width.value > 0))
|
||||
skirt_height = 1;
|
||||
|
||||
// get first skirt_height layers (maybe this should be moved to a PrintObject method?)
|
||||
const PrintObject* object0 = m_print->objects.front();
|
||||
const PrintObject* object0 = m_print->objects().front();
|
||||
std::vector<float> print_zs;
|
||||
print_zs.reserve(skirt_height * 2);
|
||||
for (size_t i = 0; i < std::min(skirt_height, object0->layers.size()); ++i)
|
||||
for (size_t i = 0; i < std::min(skirt_height, object0->layers().size()); ++i)
|
||||
{
|
||||
print_zs.push_back(float(object0->layers[i]->print_z));
|
||||
print_zs.push_back(float(object0->layers()[i]->print_z));
|
||||
}
|
||||
//FIXME why there are support layers?
|
||||
for (size_t i = 0; i < std::min(skirt_height, object0->support_layers.size()); ++i)
|
||||
for (size_t i = 0; i < std::min(skirt_height, object0->support_layers().size()); ++i)
|
||||
{
|
||||
print_zs.push_back(float(object0->support_layers[i]->print_z));
|
||||
print_zs.push_back(float(object0->support_layers()[i]->print_z));
|
||||
}
|
||||
sort_remove_duplicates(print_zs);
|
||||
if (print_zs.size() > skirt_height)
|
||||
@@ -4476,9 +4619,9 @@ void GLCanvas3D::_load_print_toolpaths()
|
||||
volume.offsets.push_back(volume.indexed_vertex_array.quad_indices.size());
|
||||
volume.offsets.push_back(volume.indexed_vertex_array.triangle_indices.size());
|
||||
if (i == 0)
|
||||
_3DScene::extrusionentity_to_verts(m_print->brim, print_zs[i], Point(0, 0), volume);
|
||||
_3DScene::extrusionentity_to_verts(m_print->brim(), print_zs[i], Point(0, 0), volume);
|
||||
|
||||
_3DScene::extrusionentity_to_verts(m_print->skirt, print_zs[i], Point(0, 0), volume);
|
||||
_3DScene::extrusionentity_to_verts(m_print->skirt(), print_zs[i], Point(0, 0), volume);
|
||||
}
|
||||
volume.bounding_box = volume.indexed_vertex_array.bounding_box();
|
||||
volume.indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized);
|
||||
@@ -4517,20 +4660,20 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||
}
|
||||
} ctxt;
|
||||
|
||||
ctxt.shifted_copies = &print_object._shifted_copies;
|
||||
ctxt.shifted_copies = &print_object.copies();
|
||||
|
||||
// order layers by print_z
|
||||
ctxt.layers.reserve(print_object.layers.size() + print_object.support_layers.size());
|
||||
for (const Layer *layer : print_object.layers)
|
||||
ctxt.layers.reserve(print_object.layers().size() + print_object.support_layers().size());
|
||||
for (const Layer *layer : print_object.layers())
|
||||
ctxt.layers.push_back(layer);
|
||||
for (const Layer *layer : print_object.support_layers)
|
||||
for (const Layer *layer : print_object.support_layers())
|
||||
ctxt.layers.push_back(layer);
|
||||
std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
|
||||
|
||||
// Maximum size of an allocation block: 32MB / sizeof(float)
|
||||
ctxt.has_perimeters = print_object.state.is_done(posPerimeters);
|
||||
ctxt.has_infill = print_object.state.is_done(posInfill);
|
||||
ctxt.has_support = print_object.state.is_done(posSupportMaterial);
|
||||
ctxt.has_perimeters = print_object.is_step_done(posPerimeters);
|
||||
ctxt.has_infill = print_object.is_step_done(posInfill);
|
||||
ctxt.has_support = print_object.is_step_done(posSupportMaterial);
|
||||
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start";
|
||||
@@ -4570,10 +4713,10 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||
}
|
||||
}
|
||||
for (const Point © : *ctxt.shifted_copies) {
|
||||
for (const LayerRegion *layerm : layer->regions) {
|
||||
for (const LayerRegion *layerm : layer->regions()) {
|
||||
if (ctxt.has_perimeters)
|
||||
_3DScene::extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
|
||||
*vols[ctxt.volume_idx(layerm->region()->config.perimeter_extruder.value, 0)]);
|
||||
*vols[ctxt.volume_idx(layerm->region()->config().perimeter_extruder.value, 0)]);
|
||||
if (ctxt.has_infill) {
|
||||
for (const ExtrusionEntity *ee : layerm->fills.entities) {
|
||||
// fill represents infill extrusions of a single island.
|
||||
@@ -4582,8 +4725,8 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||
_3DScene::extrusionentity_to_verts(*fill, float(layer->print_z), copy,
|
||||
*vols[ctxt.volume_idx(
|
||||
is_solid_infill(fill->entities.front()->role()) ?
|
||||
layerm->region()->config.solid_infill_extruder :
|
||||
layerm->region()->config.infill_extruder,
|
||||
layerm->region()->config().solid_infill_extruder :
|
||||
layerm->region()->config().infill_extruder,
|
||||
1)]);
|
||||
}
|
||||
}
|
||||
@@ -4595,8 +4738,8 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||
_3DScene::extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
|
||||
*vols[ctxt.volume_idx(
|
||||
(extrusion_entity->role() == erSupportMaterial) ?
|
||||
support_layer->object()->config.support_material_extruder :
|
||||
support_layer->object()->config.support_material_interface_extruder,
|
||||
support_layer->object()->config().support_material_extruder :
|
||||
support_layer->object()->config().support_material_interface_extruder,
|
||||
2)]);
|
||||
}
|
||||
}
|
||||
@@ -4640,10 +4783,10 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
|
||||
|
||||
void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors)
|
||||
{
|
||||
if ((m_print == nullptr) || m_print->m_wipe_tower_tool_changes.empty())
|
||||
if ((m_print == nullptr) || m_print->wipe_tower_data().tool_changes.empty())
|
||||
return;
|
||||
|
||||
if (!m_print->state.is_done(psWipeTower))
|
||||
if (!m_print->is_step_done(psWipeTower))
|
||||
return;
|
||||
|
||||
std::vector<float> tool_colors = _parse_colors(str_tool_colors);
|
||||
@@ -4671,9 +4814,10 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_
|
||||
}
|
||||
|
||||
const std::vector<WipeTower::ToolChangeResult>& tool_change(size_t idx) {
|
||||
const auto &tool_changes = print->wipe_tower_data().tool_changes;
|
||||
return priming.empty() ?
|
||||
((idx == print->m_wipe_tower_tool_changes.size()) ? final : print->m_wipe_tower_tool_changes[idx]) :
|
||||
((idx == 0) ? priming : (idx == print->m_wipe_tower_tool_changes.size() + 1) ? final : print->m_wipe_tower_tool_changes[idx - 1]);
|
||||
((idx == tool_changes.size()) ? final : tool_changes[idx]) :
|
||||
((idx == 0) ? priming : (idx == tool_changes.size() + 1) ? final : tool_changes[idx - 1]);
|
||||
}
|
||||
std::vector<WipeTower::ToolChangeResult> priming;
|
||||
std::vector<WipeTower::ToolChangeResult> final;
|
||||
@@ -4681,18 +4825,18 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_
|
||||
|
||||
ctxt.print = m_print;
|
||||
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
||||
if (m_print->m_wipe_tower_priming && m_print->config.single_extruder_multi_material_priming)
|
||||
ctxt.priming.emplace_back(*m_print->m_wipe_tower_priming.get());
|
||||
if (m_print->m_wipe_tower_final_purge)
|
||||
ctxt.final.emplace_back(*m_print->m_wipe_tower_final_purge.get());
|
||||
if (m_print->wipe_tower_data().priming && m_print->config().single_extruder_multi_material_priming)
|
||||
ctxt.priming.emplace_back(*m_print->wipe_tower_data().priming.get());
|
||||
if (m_print->wipe_tower_data().final_purge)
|
||||
ctxt.final.emplace_back(*m_print->wipe_tower_data().final_purge.get());
|
||||
|
||||
ctxt.wipe_tower_angle = ctxt.print->config.wipe_tower_rotation_angle.value/180.f * PI;
|
||||
ctxt.wipe_tower_pos = WipeTower::xy(ctxt.print->config.wipe_tower_x.value, ctxt.print->config.wipe_tower_y.value);
|
||||
ctxt.wipe_tower_angle = ctxt.print->config().wipe_tower_rotation_angle.value/180.f * PI;
|
||||
ctxt.wipe_tower_pos = WipeTower::xy(ctxt.print->config().wipe_tower_x.value, ctxt.print->config().wipe_tower_y.value);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start";
|
||||
|
||||
//FIXME Improve the heuristics for a grain size.
|
||||
size_t n_items = m_print->m_wipe_tower_tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
|
||||
size_t n_items = m_print->wipe_tower_data().tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
|
||||
size_t grain_size = std::max(n_items / 128, size_t(1));
|
||||
tbb::spin_mutex new_volume_mutex;
|
||||
auto new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* {
|
||||
@@ -5297,15 +5441,15 @@ void GLCanvas3D::_load_shells()
|
||||
size_t initial_volumes_count = m_volumes.volumes.size();
|
||||
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Shell, 0, (unsigned int)initial_volumes_count);
|
||||
|
||||
if (m_print->objects.empty())
|
||||
if (m_print->objects().empty())
|
||||
// nothing to render, return
|
||||
return;
|
||||
|
||||
// adds objects' volumes
|
||||
unsigned int object_id = 0;
|
||||
for (PrintObject* obj : m_print->objects)
|
||||
for (const PrintObject* obj : m_print->objects())
|
||||
{
|
||||
ModelObject* model_obj = obj->model_object();
|
||||
const ModelObject* model_obj = obj->model_object();
|
||||
|
||||
std::vector<int> instance_ids(model_obj->instances.size());
|
||||
for (int i = 0; i < (int)model_obj->instances.size(); ++i)
|
||||
@@ -5319,15 +5463,15 @@ void GLCanvas3D::_load_shells()
|
||||
}
|
||||
|
||||
// adds wipe tower's volume
|
||||
double max_z = m_print->objects[0]->model_object()->get_model()->bounding_box().max(2);
|
||||
const PrintConfig& config = m_print->config;
|
||||
double max_z = m_print->objects()[0]->model_object()->get_model()->bounding_box().max(2);
|
||||
const PrintConfig& config = m_print->config();
|
||||
unsigned int extruders_count = config.nozzle_diameter.size();
|
||||
if ((extruders_count > 1) && config.single_extruder_multi_material && config.wipe_tower && !config.complete_objects) {
|
||||
float depth = m_print->get_wipe_tower_depth();
|
||||
if (!m_print->state.is_done(psWipeTower))
|
||||
if (!m_print->is_step_done(psWipeTower))
|
||||
depth = (900.f/config.wipe_tower_width) * (float)(extruders_count - 1) ;
|
||||
m_volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle,
|
||||
m_use_VBOs && m_initialized, !m_print->state.is_done(psWipeTower), m_print->config.nozzle_diameter.values[0] * 1.25f * 4.5f);
|
||||
m_use_VBOs && m_initialized, !m_print->is_step_done(psWipeTower), m_print->config().nozzle_diameter.values[0] * 1.25f * 4.5f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -315,6 +315,9 @@ class GLCanvas3D
|
||||
bool dragging;
|
||||
Vec2d position;
|
||||
Drag drag;
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
bool ignore_up_event;
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
|
||||
Mouse();
|
||||
|
||||
@@ -367,7 +370,9 @@ class GLCanvas3D
|
||||
bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const;
|
||||
bool grabber_contains_mouse() const;
|
||||
void update(const Linef3& mouse_ray, const Point* mouse_pos = nullptr);
|
||||
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
void process_double_click();
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
Rect get_reset_rect_viewport(const GLCanvas3D& canvas) const;
|
||||
EType get_current_type() const;
|
||||
|
||||
@@ -383,11 +388,20 @@ class GLCanvas3D
|
||||
float get_scale() const;
|
||||
void set_scale(float scale);
|
||||
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
Vec3d get_rotation() const;
|
||||
void set_rotation(const Vec3d& rotation);
|
||||
#else
|
||||
float get_angle_z() const;
|
||||
void set_angle_z(float angle_z);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
void set_flattening_data(const ModelObject* model_object);
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
Vec3d get_flattening_rotation() const;
|
||||
#else
|
||||
Vec3d get_flattening_normal() const;
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
void set_flattening_data(const ModelObject* model_object);
|
||||
|
||||
void set_model_object_ptr(const ModelObject* model_object);
|
||||
void clicked_on_object(const Vec2d& mouse_position);
|
||||
@@ -508,8 +522,13 @@ class GLCanvas3D
|
||||
PerlCallback m_on_wipe_tower_moved_callback;
|
||||
PerlCallback m_on_enable_action_buttons_callback;
|
||||
PerlCallback m_on_gizmo_scale_uniformly_callback;
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
PerlCallback m_on_gizmo_rotate_3D_callback;
|
||||
PerlCallback m_on_gizmo_flatten_3D_callback;
|
||||
#else
|
||||
PerlCallback m_on_gizmo_rotate_callback;
|
||||
PerlCallback m_on_gizmo_flatten_callback;
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
PerlCallback m_on_update_geometry_info_callback;
|
||||
|
||||
PerlCallback m_action_add_callback;
|
||||
@@ -635,8 +654,13 @@ public:
|
||||
void register_on_wipe_tower_moved_callback(void* callback);
|
||||
void register_on_enable_action_buttons_callback(void* callback);
|
||||
void register_on_gizmo_scale_uniformly_callback(void* callback);
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
void register_on_gizmo_rotate_3D_callback(void* callback);
|
||||
void register_on_gizmo_flatten_3D_callback(void* callback);
|
||||
#else
|
||||
void register_on_gizmo_rotate_callback(void* callback);
|
||||
void register_on_gizmo_flatten_callback(void* callback);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
void register_on_update_geometry_info_callback(void* callback);
|
||||
|
||||
void register_action_add_callback(void* callback);
|
||||
|
||||
@@ -699,6 +699,21 @@ void GLCanvas3DManager::register_on_gizmo_scale_uniformly_callback(wxGLCanvas* c
|
||||
it->second->register_on_gizmo_scale_uniformly_callback(callback);
|
||||
}
|
||||
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
void GLCanvas3DManager::register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_gizmo_rotate_3D_callback(callback);
|
||||
}
|
||||
|
||||
void GLCanvas3DManager::register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_gizmo_flatten_3D_callback(callback);
|
||||
}
|
||||
#else
|
||||
void GLCanvas3DManager::register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||
@@ -712,6 +727,7 @@ void GLCanvas3DManager::register_on_gizmo_flatten_callback(wxGLCanvas* canvas, v
|
||||
if (it != m_canvases.end())
|
||||
it->second->register_on_gizmo_flatten_callback(callback);
|
||||
}
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
void GLCanvas3DManager::register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback)
|
||||
{
|
||||
|
||||
@@ -163,8 +163,13 @@ public:
|
||||
void register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback);
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
void register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback);
|
||||
#else
|
||||
void register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback);
|
||||
void register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
void register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback);
|
||||
|
||||
void register_action_add_callback(wxGLCanvas* canvas, void* callback);
|
||||
|
||||
@@ -695,6 +695,7 @@ void GLGizmoRotate3D::on_render(const BoundingBoxf3& box) const
|
||||
}
|
||||
|
||||
const float GLGizmoScale3D::Offset = 5.0f;
|
||||
const Vec3d GLGizmoScale3D::OffsetVec = (double)GLGizmoScale3D::Offset * Vec3d::Ones();
|
||||
|
||||
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent)
|
||||
: GLGizmoBase(parent)
|
||||
@@ -744,7 +745,7 @@ void GLGizmoScale3D::on_start_dragging(const BoundingBoxf3& box)
|
||||
{
|
||||
m_starting_drag_position = m_grabbers[m_hover_id].center;
|
||||
m_show_starting_box = true;
|
||||
m_starting_box = box;
|
||||
m_starting_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -760,6 +761,20 @@ void GLGizmoScale3D::on_update(const Linef3& mouse_ray, const Point* mouse_pos)
|
||||
do_scale_uniform(mouse_ray);
|
||||
}
|
||||
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
void GLGizmoScale3D::on_process_double_click()
|
||||
{
|
||||
if ((m_hover_id == 0) || (m_hover_id == 1))
|
||||
m_scale(0) = 1.0;
|
||||
else if ((m_hover_id == 2) || (m_hover_id == 3))
|
||||
m_scale(1) = 1.0;
|
||||
else if ((m_hover_id == 4) || (m_hover_id == 5))
|
||||
m_scale(2) = 1.0;
|
||||
else if (m_hover_id >= 6)
|
||||
m_scale = Vec3d::Ones();
|
||||
}
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
|
||||
void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
|
||||
{
|
||||
if (m_grabbers[0].dragging || m_grabbers[1].dragging)
|
||||
@@ -778,9 +793,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const
|
||||
|
||||
::glEnable(GL_DEPTH_TEST);
|
||||
|
||||
Vec3d offset_vec = (double)Offset * Vec3d::Ones();
|
||||
|
||||
m_box = BoundingBoxf3(box.min - offset_vec, box.max + offset_vec);
|
||||
m_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec);
|
||||
const Vec3d& center = m_box.center();
|
||||
|
||||
// x axis
|
||||
@@ -1240,15 +1253,28 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const
|
||||
::glColor4f(0.9f, 0.9f, 0.9f, 0.5f);
|
||||
|
||||
#if ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
for (const InstanceData& inst : m_instances) {
|
||||
Vec3d position = inst.position + dragged_offset;
|
||||
#else
|
||||
for (Vec3d offset : m_instances_positions) {
|
||||
offset += dragged_offset;
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
#else
|
||||
for (Vec2d offset : m_instances_positions) {
|
||||
offset += to_2d(dragged_offset);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
::glPushMatrix();
|
||||
#if ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
::glTranslated(position(0), position(1), position(2));
|
||||
::glRotated(inst.rotation(2) * 180.0 / (double)PI, 0.0, 0.0, 1.0);
|
||||
::glRotated(inst.rotation(1) * 180.0 / (double)PI, 0.0, 1.0, 0.0);
|
||||
::glRotated(inst.rotation(0) * 180.0 / (double)PI, 1.0, 0.0, 0.0);
|
||||
::glScaled(inst.scaling_factor, inst.scaling_factor, inst.scaling_factor);
|
||||
#else
|
||||
::glTranslated(offset(0), offset(1), offset(2));
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
#else
|
||||
::glTranslatef((GLfloat)offset(0), (GLfloat)offset(1), 0.0f);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
@@ -1271,13 +1297,25 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const
|
||||
{
|
||||
::glColor3f(1.0f, 1.0f, picking_color_component(i));
|
||||
#if ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
for (const InstanceData& inst : m_instances) {
|
||||
#else
|
||||
for (const Vec3d& offset : m_instances_positions) {
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
#else
|
||||
for (const Vec2d& offset : m_instances_positions) {
|
||||
#endif // ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
::glPushMatrix();
|
||||
#if ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
::glTranslated(inst.position(0), inst.position(1), inst.position(2));
|
||||
::glRotated(inst.rotation(2) * 180.0 / (double)PI, 0.0, 0.0, 1.0);
|
||||
::glRotated(inst.rotation(1) * 180.0 / (double)PI, 0.0, 1.0, 0.0);
|
||||
::glRotated(inst.rotation(0) * 180.0 / (double)PI, 1.0, 0.0, 0.0);
|
||||
::glScaled(inst.scaling_factor, inst.scaling_factor, inst.scaling_factor);
|
||||
#else
|
||||
::glTranslated(offset(0), offset(1), offset(2));
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
#else
|
||||
::glTranslatef((GLfloat)offset(0), (GLfloat)offset(1), 0.0f);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
@@ -1296,10 +1334,18 @@ void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
|
||||
|
||||
// ...and save the updated positions of the object instances:
|
||||
if (m_model_object && !m_model_object->instances.empty()) {
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
m_instances.clear();
|
||||
#else
|
||||
m_instances_positions.clear();
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
for (const auto* instance : m_model_object->instances)
|
||||
#if ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
m_instances.emplace_back(instance->get_offset(), instance->get_rotation(), instance->scaling_factor);
|
||||
#else
|
||||
m_instances_positions.emplace_back(instance->get_offset());
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
#else
|
||||
m_instances_positions.emplace_back(instance->offset);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
@@ -1315,8 +1361,10 @@ void GLGizmoFlatten::update_planes()
|
||||
for (const ModelVolume* vol : m_model_object->volumes)
|
||||
ch.merge(vol->get_convex_hull());
|
||||
ch = ch.convex_hull_3d();
|
||||
#if !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
ch.scale(m_model_object->instances.front()->scaling_factor);
|
||||
ch.rotate_z(m_model_object->instances.front()->rotation);
|
||||
#endif // !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
m_planes.clear();
|
||||
|
||||
@@ -1361,8 +1409,8 @@ void GLGizmoFlatten::update_planes()
|
||||
// if this is a just a very small triangle, remove it to speed up further calculations (it would be rejected anyway):
|
||||
if (m_planes.back().vertices.size() == 3 &&
|
||||
(m_planes.back().vertices[0] - m_planes.back().vertices[1]).norm() < 1.f
|
||||
|| (m_planes.back().vertices[0] - m_planes.back().vertices[2]).norm() < 1.f)
|
||||
m_planes.pop_back();
|
||||
|| (m_planes.back().vertices[0] - m_planes.back().vertices[2]).norm() < 1.f)
|
||||
m_planes.pop_back();
|
||||
}
|
||||
|
||||
// Now we'll go through all the polygons, transform the points into xy plane to process them:
|
||||
@@ -1465,8 +1513,10 @@ void GLGizmoFlatten::update_planes()
|
||||
m_source_data.bounding_boxes.clear();
|
||||
for (const auto& vol : m_model_object->volumes)
|
||||
m_source_data.bounding_boxes.push_back(vol->get_convex_hull().bounding_box());
|
||||
#if !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
m_source_data.scaling_factor = m_model_object->instances.front()->scaling_factor;
|
||||
m_source_data.rotation = m_model_object->instances.front()->rotation;
|
||||
#endif // !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
const float* first_vertex = m_model_object->volumes.front()->get_convex_hull().first_vertex();
|
||||
m_source_data.mesh_first_point = Vec3d((double)first_vertex[0], (double)first_vertex[1], (double)first_vertex[2]);
|
||||
}
|
||||
@@ -1478,10 +1528,14 @@ bool GLGizmoFlatten::is_plane_update_necessary() const
|
||||
if (m_state != On || !m_model_object || m_model_object->instances.empty())
|
||||
return false;
|
||||
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
if (m_model_object->volumes.size() != m_source_data.bounding_boxes.size())
|
||||
#else
|
||||
if (m_model_object->volumes.size() != m_source_data.bounding_boxes.size()
|
||||
|| m_model_object->instances.front()->scaling_factor != m_source_data.scaling_factor
|
||||
|| m_model_object->instances.front()->rotation != m_source_data.rotation)
|
||||
return true;
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
return true;
|
||||
|
||||
// now compare the bounding boxes:
|
||||
for (unsigned int i=0; i<m_model_object->volumes.size(); ++i)
|
||||
@@ -1496,11 +1550,22 @@ bool GLGizmoFlatten::is_plane_update_necessary() const
|
||||
return false;
|
||||
}
|
||||
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
Vec3d GLGizmoFlatten::get_flattening_rotation() const
|
||||
{
|
||||
// calculates the rotations in model space
|
||||
Eigen::Quaterniond q;
|
||||
Vec3d angles = q.setFromTwoVectors(m_normal, -Vec3d::UnitZ()).toRotationMatrix().eulerAngles(2, 1, 0);
|
||||
m_normal = Vec3d::Zero();
|
||||
return Vec3d(angles(2), angles(1), angles(0));
|
||||
}
|
||||
#else
|
||||
Vec3d GLGizmoFlatten::get_flattening_normal() const {
|
||||
Vec3d normal = m_model_object->instances.front()->world_matrix(true).matrix().block(0, 0, 3, 3).inverse() * m_normal;
|
||||
m_normal = Vec3d::Zero();
|
||||
return normal.normalized();
|
||||
}
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -94,6 +94,10 @@ public:
|
||||
|
||||
void update(const Linef3& mouse_ray, const Point* mouse_pos);
|
||||
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
void process_double_click() { on_process_double_click(); }
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
|
||||
void render(const BoundingBoxf3& box) const { on_render(box); }
|
||||
void render_for_picking(const BoundingBoxf3& box) const { on_render_for_picking(box); }
|
||||
|
||||
@@ -106,6 +110,9 @@ protected:
|
||||
virtual void on_start_dragging(const BoundingBoxf3& box) {}
|
||||
virtual void on_stop_dragging() {}
|
||||
virtual void on_update(const Linef3& mouse_ray, const Point* mouse_pos) = 0;
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
virtual void on_process_double_click() {}
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
virtual void on_render(const BoundingBoxf3& box) const = 0;
|
||||
virtual void on_render_for_picking(const BoundingBoxf3& box) const = 0;
|
||||
|
||||
@@ -155,6 +162,9 @@ protected:
|
||||
virtual bool on_init();
|
||||
virtual void on_start_dragging(const BoundingBoxf3& box);
|
||||
virtual void on_update(const Linef3& mouse_ray, const Point* mouse_pos);
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
virtual void on_process_double_click() { m_angle = 0.0; }
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
virtual void on_render(const BoundingBoxf3& box) const;
|
||||
virtual void on_render_for_picking(const BoundingBoxf3& box) const;
|
||||
|
||||
@@ -178,6 +188,10 @@ class GLGizmoRotate3D : public GLGizmoBase
|
||||
public:
|
||||
explicit GLGizmoRotate3D(GLCanvas3D& parent);
|
||||
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); }
|
||||
void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); }
|
||||
#else
|
||||
double get_angle_x() const { return m_gizmos[X].get_angle(); }
|
||||
void set_angle_x(double angle) { m_gizmos[X].set_angle(angle); }
|
||||
|
||||
@@ -186,6 +200,7 @@ public:
|
||||
|
||||
double get_angle_z() const { return m_gizmos[Z].get_angle(); }
|
||||
void set_angle_z(double angle) { m_gizmos[Z].set_angle(angle); }
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
protected:
|
||||
virtual bool on_init();
|
||||
@@ -222,6 +237,13 @@ protected:
|
||||
g.update(mouse_ray, mouse_pos);
|
||||
}
|
||||
}
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
virtual void on_process_double_click()
|
||||
{
|
||||
if (m_hover_id != -1)
|
||||
m_gizmos[m_hover_id].process_double_click();
|
||||
}
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
virtual void on_render(const BoundingBoxf3& box) const;
|
||||
virtual void on_render_for_picking(const BoundingBoxf3& box) const
|
||||
{
|
||||
@@ -265,6 +287,9 @@ protected:
|
||||
virtual void on_start_dragging(const BoundingBoxf3& box);
|
||||
virtual void on_stop_dragging() { m_show_starting_box = false; }
|
||||
virtual void on_update(const Linef3& mouse_ray, const Point* mouse_pos);
|
||||
#if ENABLE_GIZMOS_RESET
|
||||
virtual void on_process_double_click();
|
||||
#endif // ENABLE_GIZMOS_RESET
|
||||
virtual void on_render(const BoundingBoxf3& box) const;
|
||||
virtual void on_render_for_picking(const BoundingBoxf3& box) const;
|
||||
|
||||
@@ -320,8 +345,10 @@ private:
|
||||
};
|
||||
struct SourceDataSummary {
|
||||
std::vector<BoundingBoxf3> bounding_boxes; // bounding boxes of convex hulls of individual volumes
|
||||
#if !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
float scaling_factor;
|
||||
float rotation;
|
||||
#endif // !ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
Vec3d mesh_first_point;
|
||||
};
|
||||
|
||||
@@ -330,7 +357,19 @@ private:
|
||||
|
||||
std::vector<PlaneData> m_planes;
|
||||
#if ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
struct InstanceData
|
||||
{
|
||||
Vec3d position;
|
||||
Vec3d rotation;
|
||||
double scaling_factor;
|
||||
|
||||
InstanceData(const Vec3d& position, const Vec3d& rotation, double scaling_factor) : position(position), rotation(rotation), scaling_factor(scaling_factor) {}
|
||||
};
|
||||
std::vector<InstanceData> m_instances;
|
||||
#else
|
||||
Pointf3s m_instances_positions;
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
#else
|
||||
std::vector<Vec2d> m_instances_positions;
|
||||
#endif // ENABLE_MODELINSTANCE_3D_OFFSET
|
||||
@@ -344,7 +383,11 @@ public:
|
||||
explicit GLGizmoFlatten(GLCanvas3D& parent);
|
||||
|
||||
void set_flattening_data(const ModelObject* model_object);
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
Vec3d get_flattening_rotation() const;
|
||||
#else
|
||||
Vec3d get_flattening_normal() const;
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
protected:
|
||||
virtual bool on_init();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define slic3r_GLToolbar_hpp_
|
||||
|
||||
#include "../../slic3r/GUI/GLTexture.hpp"
|
||||
#include "../../libslic3r/Utils.hpp"
|
||||
#include "../../callback.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "GUI.hpp"
|
||||
#include "../AppController.hpp"
|
||||
#include "WipeTowerDialog.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
@@ -46,9 +47,12 @@
|
||||
|
||||
#include "Tab.hpp"
|
||||
#include "TabIface.hpp"
|
||||
#include "GUI_Preview.hpp"
|
||||
#include "GUI_PreviewIface.hpp"
|
||||
#include "AboutDialog.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#include "ConfigSnapshotDialog.hpp"
|
||||
#include "ProgressStatusBar.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "ConfigWizard.hpp"
|
||||
@@ -66,6 +70,8 @@
|
||||
#include "Model.hpp"
|
||||
#include "LambdaObjectDialog.hpp"
|
||||
|
||||
#include "../../libslic3r/Print.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
#if __APPLE__
|
||||
@@ -113,7 +119,9 @@ void break_to_debugger()
|
||||
// Passing the wxWidgets GUI classes instantiated by the Perl part to C++.
|
||||
wxApp *g_wxApp = nullptr;
|
||||
wxFrame *g_wxMainFrame = nullptr;
|
||||
ProgressStatusBar *g_progress_status_bar = nullptr;
|
||||
wxNotebook *g_wxTabPanel = nullptr;
|
||||
wxPanel *g_wxPlater = nullptr;
|
||||
AppConfig *g_AppConfig = nullptr;
|
||||
PresetBundle *g_PresetBundle= nullptr;
|
||||
PresetUpdater *g_PresetUpdater = nullptr;
|
||||
@@ -143,6 +151,8 @@ wxStaticBitmap *g_manifold_warning_icon = nullptr;
|
||||
bool g_show_print_info = false;
|
||||
bool g_show_manifold_warning_icon = false;
|
||||
|
||||
PreviewIface* g_preview = nullptr;
|
||||
|
||||
static void init_label_colours()
|
||||
{
|
||||
auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
@@ -199,11 +209,23 @@ void set_main_frame(wxFrame *main_frame)
|
||||
|
||||
wxFrame* get_main_frame() { return g_wxMainFrame; }
|
||||
|
||||
void set_progress_status_bar(ProgressStatusBar *prsb)
|
||||
{
|
||||
g_progress_status_bar = prsb;
|
||||
}
|
||||
|
||||
ProgressStatusBar* get_progress_status_bar() { return g_progress_status_bar; }
|
||||
|
||||
void set_tab_panel(wxNotebook *tab_panel)
|
||||
{
|
||||
g_wxTabPanel = tab_panel;
|
||||
}
|
||||
|
||||
void set_plater(wxPanel *plater)
|
||||
{
|
||||
g_wxPlater = plater;
|
||||
}
|
||||
|
||||
void set_app_config(AppConfig *app_config)
|
||||
{
|
||||
g_AppConfig = app_config;
|
||||
@@ -607,13 +629,13 @@ void open_preferences_dialog(int event_preferences)
|
||||
dlg->ShowModal();
|
||||
}
|
||||
|
||||
void create_preset_tabs(bool no_controller, int event_value_change, int event_presets_changed)
|
||||
void create_preset_tabs(int event_value_change, int event_presets_changed)
|
||||
{
|
||||
update_label_colours_from_appconfig();
|
||||
add_created_tab(new TabPrint (g_wxTabPanel, no_controller), event_value_change, event_presets_changed);
|
||||
add_created_tab(new TabFilament (g_wxTabPanel, no_controller), event_value_change, event_presets_changed);
|
||||
add_created_tab(new TabSLAMaterial (g_wxTabPanel, no_controller), event_value_change, event_presets_changed);
|
||||
add_created_tab(new TabPrinter (g_wxTabPanel, no_controller), event_value_change, event_presets_changed);
|
||||
add_created_tab(new TabPrint (g_wxTabPanel), event_value_change, event_presets_changed);
|
||||
add_created_tab(new TabFilament (g_wxTabPanel), event_value_change, event_presets_changed);
|
||||
add_created_tab(new TabSLAMaterial (g_wxTabPanel), event_value_change, event_presets_changed);
|
||||
add_created_tab(new TabPrinter (g_wxTabPanel), event_value_change, event_presets_changed);
|
||||
}
|
||||
|
||||
std::vector<PresetTab> preset_tabs = {
|
||||
@@ -648,6 +670,17 @@ TabIface* get_preset_tab_iface(char *name)
|
||||
return new TabIface(nullptr);
|
||||
}
|
||||
|
||||
PreviewIface* create_preview_iface(wxNotebook* parent, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data)
|
||||
{
|
||||
if (g_preview == nullptr)
|
||||
{
|
||||
Preview* panel = new Preview(parent, config, print, gcode_preview_data);
|
||||
g_preview = new PreviewIface(panel);
|
||||
}
|
||||
|
||||
return g_preview;
|
||||
}
|
||||
|
||||
// opt_index = 0, by the reason of zero-index in ConfigOptionVector by default (in case only one element)
|
||||
void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index /*= 0*/)
|
||||
{
|
||||
@@ -809,6 +842,18 @@ void warning_catcher(wxWindow* parent, const wxString& message){
|
||||
msg.ShowModal();
|
||||
}
|
||||
|
||||
// Assign a Lambda to the print object to emit a wxWidgets Command with the provided ID
|
||||
// to deliver a progress status message.
|
||||
void set_print_callback_event(Print *print, int id)
|
||||
{
|
||||
print->set_status_callback([id](int percent, const std::string &message){
|
||||
wxCommandEvent event(id);
|
||||
event.SetInt(percent);
|
||||
event.SetString(message);
|
||||
wxQueueEvent(g_wxMainFrame, event.Clone());
|
||||
});
|
||||
}
|
||||
|
||||
wxApp* get_app(){
|
||||
return g_wxApp;
|
||||
}
|
||||
@@ -947,6 +992,12 @@ wxString from_u8(const std::string &str)
|
||||
return wxString::FromUTF8(str.c_str());
|
||||
}
|
||||
|
||||
std::string into_u8(const wxString &str)
|
||||
{
|
||||
auto buffer_utf8 = str.utf8_str();
|
||||
return std::string(buffer_utf8.data());
|
||||
}
|
||||
|
||||
void set_model_events_from_perl(Model &model,
|
||||
int event_object_selection_changed,
|
||||
int event_object_settings_changed,
|
||||
@@ -1355,4 +1406,23 @@ void desktop_open_datadir_folder()
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace {
|
||||
AppControllerPtr g_appctl;
|
||||
}
|
||||
|
||||
AppControllerPtr get_appctl()
|
||||
{
|
||||
return g_appctl;
|
||||
}
|
||||
|
||||
void set_cli_appctl()
|
||||
{
|
||||
g_appctl = std::make_shared<AppControllerCli>();
|
||||
}
|
||||
|
||||
void set_gui_appctl()
|
||||
{
|
||||
g_appctl = std::make_shared<AppControllerGui>();
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "PrintConfig.hpp"
|
||||
#include "../../libslic3r/Utils.hpp"
|
||||
#include "../../callback.hpp"
|
||||
#include "GUI_ObjectParts.hpp"
|
||||
|
||||
#include <wx/intl.h>
|
||||
@@ -15,6 +15,7 @@ class wxWindow;
|
||||
class wxFrame;
|
||||
class wxMenuBar;
|
||||
class wxNotebook;
|
||||
class wxPanel;
|
||||
class wxComboCtrl;
|
||||
class wxString;
|
||||
class wxArrayString;
|
||||
@@ -32,10 +33,18 @@ namespace Slic3r {
|
||||
|
||||
class PresetBundle;
|
||||
class PresetCollection;
|
||||
class Print;
|
||||
class ProgressStatusBar;
|
||||
class AppConfig;
|
||||
class PresetUpdater;
|
||||
class DynamicPrintConfig;
|
||||
class TabIface;
|
||||
class PreviewIface;
|
||||
class Print;
|
||||
class GCodePreviewData;
|
||||
class AppControllerBase;
|
||||
|
||||
using AppControllerPtr = std::shared_ptr<AppControllerBase>;
|
||||
|
||||
#define _(s) Slic3r::GUI::I18N::translate((s))
|
||||
|
||||
@@ -97,7 +106,9 @@ void break_to_debugger();
|
||||
// Passing the wxWidgets GUI classes instantiated by the Perl part to C++.
|
||||
void set_wxapp(wxApp *app);
|
||||
void set_main_frame(wxFrame *main_frame);
|
||||
void set_progress_status_bar(ProgressStatusBar *prsb);
|
||||
void set_tab_panel(wxNotebook *tab_panel);
|
||||
void set_plater(wxPanel *plater);
|
||||
void set_app_config(AppConfig *app_config);
|
||||
void set_preset_bundle(PresetBundle *preset_bundle);
|
||||
void set_preset_updater(PresetUpdater *updater);
|
||||
@@ -117,9 +128,14 @@ AppConfig* get_app_config();
|
||||
wxApp* get_app();
|
||||
PresetBundle* get_preset_bundle();
|
||||
wxFrame* get_main_frame();
|
||||
ProgressStatusBar* get_progress_status_bar();
|
||||
wxNotebook * get_tab_panel();
|
||||
wxNotebook* get_tab_panel();
|
||||
|
||||
AppControllerPtr get_appctl();
|
||||
void set_cli_appctl();
|
||||
void set_gui_appctl();
|
||||
|
||||
const wxColour& get_label_clr_modified();
|
||||
const wxColour& get_label_clr_sys();
|
||||
const wxColour& get_label_clr_default();
|
||||
@@ -156,9 +172,11 @@ extern void config_wizard(int run_reason);
|
||||
extern void open_preferences_dialog(int event_preferences);
|
||||
|
||||
// Create a new preset tab (print, filament and printer),
|
||||
void create_preset_tabs(bool no_controller, int event_value_change, int event_presets_changed);
|
||||
void create_preset_tabs(int event_value_change, int event_presets_changed);
|
||||
TabIface* get_preset_tab_iface(char *name);
|
||||
|
||||
PreviewIface* create_preview_iface(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data);
|
||||
|
||||
// add it at the end of the tab panel.
|
||||
void add_created_tab(Tab* panel, int event_value_change, int event_presets_changed);
|
||||
// Change option value in config
|
||||
@@ -172,6 +190,10 @@ void show_error_id(int id, const std::string& message); // For Perl
|
||||
void show_info(wxWindow* parent, const wxString& message, const wxString& title);
|
||||
void warning_catcher(wxWindow* parent, const wxString& message);
|
||||
|
||||
// Assign a Lambda to the print object to emit a wxWidgets Command with the provided ID
|
||||
// to deliver a progress status message.
|
||||
void set_print_callback_event(Print *print, int id);
|
||||
|
||||
// load language saved at application config
|
||||
bool load_language();
|
||||
// save language at application config
|
||||
@@ -202,6 +224,8 @@ int combochecklist_get_flags(wxComboCtrl* comboCtrl);
|
||||
wxString L_str(const std::string &str);
|
||||
// Return wxString from std::string in UTF8
|
||||
wxString from_u8(const std::string &str);
|
||||
// Return std::string in UTF8 from wxString
|
||||
std::string into_u8(const wxString &str);
|
||||
|
||||
void set_model_events_from_perl(Model &model,
|
||||
int event_object_selection_changed,
|
||||
|
||||
@@ -387,13 +387,10 @@ void update_after_moving()
|
||||
if (volume_id < 0)
|
||||
return;
|
||||
|
||||
Vec3d m = m_move_options;
|
||||
Vec3d l = m_last_coords;
|
||||
|
||||
auto d = Vec3d(m(0) - l(0), m(1) - l(1), m(2) - l(2));
|
||||
auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
|
||||
auto d = m_move_options - m_last_coords;
|
||||
auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
|
||||
volume->mesh.translate(d(0), d(1), d(2));
|
||||
m_last_coords = m;
|
||||
m_last_coords = m_move_options;
|
||||
|
||||
m_parts_changed = true;
|
||||
parts_changed(m_selected_object_id);
|
||||
@@ -1805,11 +1802,15 @@ void update_scale_values(double scaling_factor)
|
||||
|
||||
void update_rotation_values()
|
||||
{
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
update_rotation_value((*m_objects)[m_selected_object_id]->instances.front()->get_rotation());
|
||||
#else
|
||||
auto og = get_optgroup(ogFrequentlyObjectSettings);
|
||||
auto instance = (*m_objects)[m_selected_object_id]->instances.front();
|
||||
og->set_value("rotation_x", 0);
|
||||
og->set_value("rotation_y", 0);
|
||||
og->set_value("rotation_z", int(Geometry::rad2deg(instance->rotation)));
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
}
|
||||
|
||||
void update_rotation_value(double angle, Axis axis)
|
||||
@@ -1836,9 +1837,19 @@ void update_rotation_value(double angle, Axis axis)
|
||||
}
|
||||
}
|
||||
|
||||
og->set_value(axis_str, int(Geometry::rad2deg(angle)));
|
||||
og->set_value(axis_str, round_nearest(int(Geometry::rad2deg(angle)), 0));
|
||||
}
|
||||
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
void update_rotation_value(const Vec3d& rotation)
|
||||
{
|
||||
auto og = get_optgroup(ogFrequentlyObjectSettings);
|
||||
og->set_value("rotation_x", int(round_nearest(Geometry::rad2deg(rotation(0)), 0)));
|
||||
og->set_value("rotation_y", int(round_nearest(Geometry::rad2deg(rotation(1)), 0)));
|
||||
og->set_value("rotation_z", int(round_nearest(Geometry::rad2deg(rotation(2)), 0)));
|
||||
}
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
|
||||
void set_uniform_scaling(const bool uniform_scale)
|
||||
{
|
||||
g_is_uniform_scale = uniform_scale;
|
||||
|
||||
@@ -124,6 +124,9 @@ void update_scale_values(double scaling_factor);
|
||||
void update_rotation_values();
|
||||
// update rotation value after "gizmos"
|
||||
void update_rotation_value(double angle, Axis axis);
|
||||
#if ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
void update_rotation_value(const Vec3d& rotation);
|
||||
#endif // ENABLE_MODELINSTANCE_3D_ROTATION
|
||||
void set_uniform_scaling(const bool uniform_scale);
|
||||
|
||||
void on_begin_drag(wxDataViewEvent &event);
|
||||
|
||||
@@ -0,0 +1,489 @@
|
||||
#include "../../libslic3r/libslic3r.h"
|
||||
#include "GUI_Preview.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "AppConfig.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "../../libslic3r/GCode/PreviewData.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/glcanvas.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/combo.h>
|
||||
#include <wx/checkbox.h>
|
||||
|
||||
// this include must follow the wxWidgets ones or it won't compile on Windows -> see http://trac.wxwidgets.org/ticket/2421
|
||||
#include "../../libslic3r/Print.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
Preview::Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data)
|
||||
: m_canvas(nullptr)
|
||||
, m_double_slider_sizer(nullptr)
|
||||
, m_label_view_type(nullptr)
|
||||
, m_choice_view_type(nullptr)
|
||||
, m_label_show_features(nullptr)
|
||||
, m_combochecklist_features(nullptr)
|
||||
, m_checkbox_travel(nullptr)
|
||||
, m_checkbox_retractions(nullptr)
|
||||
, m_checkbox_unretractions(nullptr)
|
||||
, m_checkbox_shells(nullptr)
|
||||
, m_config(config)
|
||||
, m_print(print)
|
||||
, m_gcode_preview_data(gcode_preview_data)
|
||||
, m_number_extruders(1)
|
||||
, m_preferred_color_mode("feature")
|
||||
, m_loaded(false)
|
||||
, m_enabled(false)
|
||||
, m_force_sliders_full_range(false)
|
||||
{
|
||||
if (init(notebook, config, print, gcode_preview_data))
|
||||
{
|
||||
notebook->AddPage(this, _(L("Preview")));
|
||||
show_hide_ui_elements("none");
|
||||
load_print();
|
||||
}
|
||||
}
|
||||
|
||||
bool Preview::init(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data)
|
||||
{
|
||||
if ((notebook == nullptr) || (config == nullptr) || (print == nullptr) || (gcode_preview_data == nullptr))
|
||||
return false;
|
||||
|
||||
// creates this panel add append it to the given notebook as a new page
|
||||
if (!Create(notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize))
|
||||
return false;
|
||||
|
||||
int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, WX_GL_SAMPLE_BUFFERS, GL_TRUE, WX_GL_SAMPLES, 4, 0 };
|
||||
|
||||
int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER;
|
||||
const AppConfig* app_config = GUI::get_app_config();
|
||||
bool enable_multisample = (app_config != nullptr) && (app_config->get("use_legacy_opengl") != "1") && (wxVersion >= 30003);
|
||||
|
||||
// if multisample is not enabled or supported by the graphic card, remove it from the attributes list
|
||||
bool can_multisample = enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample");
|
||||
// bool can_multisample = enable_multisample && wxGLCanvas::IsDisplaySupported(attribList); // <<< Alternative method: but IsDisplaySupported() seems not to work
|
||||
if (!can_multisample)
|
||||
attribList[4] = 0;
|
||||
|
||||
m_canvas = new wxGLCanvas(this, wxID_ANY, attribList);
|
||||
if (m_canvas == nullptr)
|
||||
return false;
|
||||
|
||||
_3DScene::add_canvas(m_canvas);
|
||||
_3DScene::allow_multisample(m_canvas, can_multisample);
|
||||
_3DScene::enable_shader(m_canvas, true);
|
||||
_3DScene::set_config(m_canvas, m_config);
|
||||
_3DScene::set_print(m_canvas, m_print);
|
||||
_3DScene::enable_legend_texture(m_canvas, true);
|
||||
_3DScene::enable_dynamic_background(m_canvas, true);
|
||||
|
||||
m_double_slider_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
create_double_slider(this, m_double_slider_sizer, m_canvas);
|
||||
|
||||
m_label_view_type = new wxStaticText(this, wxID_ANY, _(L("View")));
|
||||
|
||||
m_choice_view_type = new wxChoice(this, wxID_ANY);
|
||||
m_choice_view_type->Append(_(L("Feature type")));
|
||||
m_choice_view_type->Append(_(L("Height")));
|
||||
m_choice_view_type->Append(_(L("Width")));
|
||||
m_choice_view_type->Append(_(L("Speed")));
|
||||
m_choice_view_type->Append(_(L("Volumetric flow rate")));
|
||||
m_choice_view_type->Append(_(L("Tool")));
|
||||
m_choice_view_type->SetSelection(0);
|
||||
|
||||
m_label_show_features = new wxStaticText(this, wxID_ANY, _(L("Show")));
|
||||
|
||||
m_combochecklist_features = new wxComboCtrl();
|
||||
m_combochecklist_features->Create(this, wxID_ANY, _(L("Feature types")), wxDefaultPosition, wxSize(200, -1), wxCB_READONLY);
|
||||
std::string feature_text = GUI::into_u8(_(L("Feature types")));
|
||||
std::string feature_items = GUI::into_u8(
|
||||
_(L("Perimeter")) + "|" +
|
||||
_(L("External perimeter")) + "|" +
|
||||
_(L("Overhang perimeter")) + "|" +
|
||||
_(L("Internal infill")) + "|" +
|
||||
_(L("Solid infill")) + "|" +
|
||||
_(L("Top solid infill")) + "|" +
|
||||
_(L("Bridge infill")) + "|" +
|
||||
_(L("Gap fill")) + "|" +
|
||||
_(L("Skirt")) + "|" +
|
||||
_(L("Support material")) + "|" +
|
||||
_(L("Support material interface")) + "|" +
|
||||
_(L("Wipe tower")) + "|" +
|
||||
_(L("Custom"))
|
||||
);
|
||||
Slic3r::GUI::create_combochecklist(m_combochecklist_features, feature_text, feature_items, true);
|
||||
|
||||
m_checkbox_travel = new wxCheckBox(this, wxID_ANY, _(L("Travel")));
|
||||
m_checkbox_retractions = new wxCheckBox(this, wxID_ANY, _(L("Retractions")));
|
||||
m_checkbox_unretractions = new wxCheckBox(this, wxID_ANY, _(L("Unretractions")));
|
||||
m_checkbox_shells = new wxCheckBox(this, wxID_ANY, _(L("Shells")));
|
||||
|
||||
wxBoxSizer* top_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
top_sizer->Add(m_canvas, 1, wxALL | wxEXPAND, 0);
|
||||
top_sizer->Add(m_double_slider_sizer, 0, wxEXPAND, 0);
|
||||
|
||||
wxBoxSizer* bottom_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
bottom_sizer->Add(m_label_view_type, 0, wxALIGN_CENTER_VERTICAL, 5);
|
||||
bottom_sizer->Add(m_choice_view_type, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
bottom_sizer->AddSpacer(10);
|
||||
bottom_sizer->Add(m_label_show_features, 0, wxALIGN_CENTER_VERTICAL, 5);
|
||||
bottom_sizer->Add(m_combochecklist_features, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
bottom_sizer->AddSpacer(20);
|
||||
bottom_sizer->Add(m_checkbox_travel, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
bottom_sizer->AddSpacer(10);
|
||||
bottom_sizer->Add(m_checkbox_retractions, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
bottom_sizer->AddSpacer(10);
|
||||
bottom_sizer->Add(m_checkbox_unretractions, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
bottom_sizer->AddSpacer(10);
|
||||
bottom_sizer->Add(m_checkbox_shells, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(top_sizer, 1, wxALL | wxEXPAND, 0);
|
||||
main_sizer->Add(bottom_sizer, 0, wxALL | wxEXPAND, 0);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
SetMinSize(GetSize());
|
||||
GetSizer()->SetSizeHints(this);
|
||||
|
||||
bind_event_handlers();
|
||||
|
||||
// sets colors for gcode preview extrusion roles
|
||||
std::vector<std::string> extrusion_roles_colors = {
|
||||
"Perimeter", "FFFF66",
|
||||
"External perimeter", "FFA500",
|
||||
"Overhang perimeter", "0000FF",
|
||||
"Internal infill", "B1302A",
|
||||
"Solid infill", "D732D7",
|
||||
"Top solid infill", "FF1A1A",
|
||||
"Bridge infill", "9999FF",
|
||||
"Gap fill", "FFFFFF",
|
||||
"Skirt", "845321",
|
||||
"Support material", "00FF00",
|
||||
"Support material interface", "008000",
|
||||
"Wipe tower", "B3E3AB",
|
||||
"Custom", "28CC94"
|
||||
};
|
||||
m_gcode_preview_data->set_extrusion_paths_colors(extrusion_roles_colors);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Preview::~Preview()
|
||||
{
|
||||
unbind_event_handlers();
|
||||
|
||||
if (m_canvas != nullptr)
|
||||
{
|
||||
_3DScene::remove_canvas(m_canvas);
|
||||
delete m_canvas;
|
||||
}
|
||||
}
|
||||
|
||||
void Preview::register_on_viewport_changed_callback(void* callback)
|
||||
{
|
||||
if ((m_canvas != nullptr) && (callback != nullptr))
|
||||
_3DScene::register_on_viewport_changed_callback(m_canvas, callback);
|
||||
}
|
||||
|
||||
void Preview::set_number_extruders(unsigned int number_extruders)
|
||||
{
|
||||
if (m_number_extruders != number_extruders)
|
||||
{
|
||||
m_number_extruders = number_extruders;
|
||||
int type = 0; // color by a feature type
|
||||
if (number_extruders > 1)
|
||||
{
|
||||
int tool_idx = m_choice_view_type->FindString(_(L("Tool")));
|
||||
int type = (number_extruders > 1) ? tool_idx /* color by a tool number */ : 0; // color by a feature type
|
||||
m_choice_view_type->SetSelection(type);
|
||||
if ((0 <= type) && (type < (int)GCodePreviewData::Extrusion::Num_View_Types))
|
||||
m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
|
||||
|
||||
m_preferred_color_mode = (type == tool_idx) ? "tool_or_feature" : "feature";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Preview::reset_gcode_preview_data()
|
||||
{
|
||||
m_gcode_preview_data->reset();
|
||||
_3DScene::reset_legend_texture();
|
||||
}
|
||||
|
||||
void Preview::set_canvas_as_dirty()
|
||||
{
|
||||
if (m_canvas != nullptr)
|
||||
_3DScene::set_as_dirty(m_canvas);
|
||||
}
|
||||
|
||||
void Preview::set_enabled(bool enabled)
|
||||
{
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
void Preview::set_bed_shape(const Pointfs& shape)
|
||||
{
|
||||
if (m_canvas != nullptr)
|
||||
_3DScene::set_bed_shape(m_canvas, shape);
|
||||
}
|
||||
|
||||
void Preview::select_view(const std::string& direction)
|
||||
{
|
||||
if (m_canvas != nullptr)
|
||||
_3DScene::select_view(m_canvas, direction);
|
||||
}
|
||||
|
||||
void Preview::set_viewport_from_scene(wxGLCanvas* canvas)
|
||||
{
|
||||
if ((m_canvas != nullptr) && (canvas != nullptr))
|
||||
_3DScene::set_viewport_from_scene(m_canvas, canvas);
|
||||
}
|
||||
|
||||
void Preview::set_viewport_into_scene(wxGLCanvas* canvas)
|
||||
{
|
||||
if ((m_canvas != nullptr) && (canvas != nullptr))
|
||||
_3DScene::set_viewport_from_scene(canvas, m_canvas);
|
||||
}
|
||||
|
||||
void Preview::set_drop_target(wxDropTarget* target)
|
||||
{
|
||||
if (target != nullptr)
|
||||
SetDropTarget(target);
|
||||
}
|
||||
|
||||
void Preview::load_print()
|
||||
{
|
||||
if (m_loaded)
|
||||
return;
|
||||
|
||||
// we require that there's at least one object and the posSlice step
|
||||
// is performed on all of them(this ensures that _shifted_copies was
|
||||
// populated and we know the number of layers)
|
||||
unsigned int n_layers = 0;
|
||||
if (m_print->is_step_done(posSlice))
|
||||
{
|
||||
std::set<float> zs;
|
||||
for (const PrintObject* print_object : m_print->objects())
|
||||
{
|
||||
const LayerPtrs& layers = print_object->layers();
|
||||
const SupportLayerPtrs& support_layers = print_object->support_layers();
|
||||
for (const Layer* layer : layers)
|
||||
{
|
||||
zs.insert(layer->print_z);
|
||||
}
|
||||
for (const SupportLayer* layer : support_layers)
|
||||
{
|
||||
zs.insert(layer->print_z);
|
||||
}
|
||||
}
|
||||
|
||||
n_layers = (unsigned int)zs.size();
|
||||
}
|
||||
|
||||
if (n_layers == 0)
|
||||
{
|
||||
reset_sliders();
|
||||
_3DScene::reset_legend_texture();
|
||||
if (m_canvas)
|
||||
m_canvas->Refresh();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_preferred_color_mode == "tool_or_feature")
|
||||
{
|
||||
// It is left to Slic3r to decide whether the print shall be colored by the tool or by the feature.
|
||||
// Color by feature if it is a single extruder print.
|
||||
unsigned int number_extruders = (unsigned int)m_print->extruders().size();
|
||||
int tool_idx = m_choice_view_type->FindString(_(L("Tool")));
|
||||
int type = (number_extruders > 1) ? tool_idx /* color by a tool number */ : 0; // color by a feature type
|
||||
m_choice_view_type->SetSelection(type);
|
||||
if ((0 <= type) && (type < (int)GCodePreviewData::Extrusion::Num_View_Types))
|
||||
m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
|
||||
// If the->SetSelection changed the following line, revert it to "decide yourself".
|
||||
m_preferred_color_mode = "tool_or_feature";
|
||||
}
|
||||
|
||||
// Collect colors per extruder.
|
||||
std::vector<std::string> colors;
|
||||
if (!m_gcode_preview_data->empty() || (m_gcode_preview_data->extrusion.view_type == GCodePreviewData::Extrusion::Tool))
|
||||
{
|
||||
const ConfigOptionStrings* extruders_opt = dynamic_cast<const ConfigOptionStrings*>(m_config->option("extruder_colour"));
|
||||
const ConfigOptionStrings* filamemts_opt = dynamic_cast<const ConfigOptionStrings*>(m_config->option("filament_colour"));
|
||||
unsigned int colors_count = std::max((unsigned int)extruders_opt->values.size(), (unsigned int)filamemts_opt->values.size());
|
||||
|
||||
unsigned char rgb[3];
|
||||
for (unsigned int i = 0; i < colors_count; ++i)
|
||||
{
|
||||
std::string color = m_config->opt_string("extruder_colour", i);
|
||||
if (!PresetBundle::parse_color(color, rgb))
|
||||
{
|
||||
color = m_config->opt_string("filament_colour", i);
|
||||
if (!PresetBundle::parse_color(color, rgb))
|
||||
color = "#FFFFFF";
|
||||
}
|
||||
|
||||
colors.push_back(color);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsShown() && (m_canvas != nullptr))
|
||||
{
|
||||
// used to set the sliders to the extremes of the current zs range
|
||||
m_force_sliders_full_range = false;
|
||||
|
||||
if (m_gcode_preview_data->empty())
|
||||
{
|
||||
// load skirt and brim
|
||||
_3DScene::load_preview(m_canvas, colors);
|
||||
show_hide_ui_elements("simple");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_force_sliders_full_range = (_3DScene::get_volumes_count(m_canvas) == 0);
|
||||
_3DScene::load_gcode_preview(m_canvas, m_gcode_preview_data, colors);
|
||||
show_hide_ui_elements("full");
|
||||
|
||||
// recalculates zs and update sliders accordingly
|
||||
n_layers = (unsigned int)_3DScene::get_current_print_zs(m_canvas, true).size();
|
||||
if (n_layers == 0)
|
||||
{
|
||||
// all layers filtered out
|
||||
reset_sliders();
|
||||
m_canvas->Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
if (n_layers > 0)
|
||||
update_sliders();
|
||||
|
||||
m_loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Preview::reload_print(bool force)
|
||||
{
|
||||
_3DScene::reset_volumes(m_canvas);
|
||||
m_loaded = false;
|
||||
|
||||
if (!IsShown() && !force)
|
||||
return;
|
||||
|
||||
load_print();
|
||||
}
|
||||
|
||||
void Preview::refresh_print()
|
||||
{
|
||||
m_loaded = false;
|
||||
|
||||
if (!IsShown())
|
||||
return;
|
||||
|
||||
load_print();
|
||||
}
|
||||
|
||||
void Preview::bind_event_handlers()
|
||||
{
|
||||
this->Bind(wxEVT_SIZE, &Preview::on_size, this);
|
||||
m_choice_view_type->Bind(wxEVT_CHOICE, &Preview::on_choice_view_type, this);
|
||||
m_combochecklist_features->Bind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this);
|
||||
m_checkbox_travel->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_travel, this);
|
||||
m_checkbox_retractions->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_retractions, this);
|
||||
m_checkbox_unretractions->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_unretractions, this);
|
||||
m_checkbox_shells->Bind(wxEVT_CHECKBOX, &Preview::on_checkbox_shells, this);
|
||||
}
|
||||
|
||||
void Preview::unbind_event_handlers()
|
||||
{
|
||||
this->Unbind(wxEVT_SIZE, &Preview::on_size, this);
|
||||
m_choice_view_type->Unbind(wxEVT_CHOICE, &Preview::on_choice_view_type, this);
|
||||
m_combochecklist_features->Unbind(wxEVT_CHECKLISTBOX, &Preview::on_combochecklist_features, this);
|
||||
m_checkbox_travel->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_travel, this);
|
||||
m_checkbox_retractions->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_retractions, this);
|
||||
m_checkbox_unretractions->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_unretractions, this);
|
||||
m_checkbox_shells->Unbind(wxEVT_CHECKBOX, &Preview::on_checkbox_shells, this);
|
||||
}
|
||||
|
||||
void Preview::show_hide_ui_elements(const std::string& what)
|
||||
{
|
||||
bool enable = (what == "full");
|
||||
m_label_show_features->Enable(enable);
|
||||
m_combochecklist_features->Enable(enable);
|
||||
m_checkbox_travel->Enable(enable);
|
||||
m_checkbox_retractions->Enable(enable);
|
||||
m_checkbox_unretractions->Enable(enable);
|
||||
m_checkbox_shells->Enable(enable);
|
||||
|
||||
enable = (what != "none");
|
||||
m_label_view_type->Enable(enable);
|
||||
m_choice_view_type->Enable(enable);
|
||||
}
|
||||
|
||||
void Preview::reset_sliders()
|
||||
{
|
||||
m_enabled = false;
|
||||
reset_double_slider();
|
||||
m_double_slider_sizer->Hide((size_t)0);
|
||||
}
|
||||
|
||||
void Preview::update_sliders()
|
||||
{
|
||||
m_enabled = true;
|
||||
update_double_slider(m_force_sliders_full_range);
|
||||
m_double_slider_sizer->Show((size_t)0);
|
||||
Layout();
|
||||
}
|
||||
|
||||
void Preview::on_size(wxSizeEvent& evt)
|
||||
{
|
||||
evt.Skip();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void Preview::on_choice_view_type(wxCommandEvent& evt)
|
||||
{
|
||||
m_preferred_color_mode = (m_choice_view_type->GetStringSelection() == L("Tool")) ? "tool" : "feature";
|
||||
int selection = m_choice_view_type->GetCurrentSelection();
|
||||
if ((0 <= selection) && (selection < (int)GCodePreviewData::Extrusion::Num_View_Types))
|
||||
m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)selection;
|
||||
|
||||
reload_print();
|
||||
}
|
||||
|
||||
void Preview::on_combochecklist_features(wxCommandEvent& evt)
|
||||
{
|
||||
int flags = Slic3r::GUI::combochecklist_get_flags(m_combochecklist_features);
|
||||
m_gcode_preview_data->extrusion.role_flags = (unsigned int)flags;
|
||||
refresh_print();
|
||||
}
|
||||
|
||||
void Preview::on_checkbox_travel(wxCommandEvent& evt)
|
||||
{
|
||||
m_gcode_preview_data->travel.is_visible = m_checkbox_travel->IsChecked();
|
||||
refresh_print();
|
||||
}
|
||||
|
||||
void Preview::on_checkbox_retractions(wxCommandEvent& evt)
|
||||
{
|
||||
m_gcode_preview_data->retraction.is_visible = m_checkbox_retractions->IsChecked();
|
||||
refresh_print();
|
||||
}
|
||||
|
||||
void Preview::on_checkbox_unretractions(wxCommandEvent& evt)
|
||||
{
|
||||
m_gcode_preview_data->unretraction.is_visible = m_checkbox_unretractions->IsChecked();
|
||||
refresh_print();
|
||||
}
|
||||
|
||||
void Preview::on_checkbox_shells(wxCommandEvent& evt)
|
||||
{
|
||||
m_gcode_preview_data->shell.is_visible = m_checkbox_shells->IsChecked();
|
||||
refresh_print();
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef slic3r_GUI_Preview_hpp_
|
||||
#define slic3r_GUI_Preview_hpp_
|
||||
|
||||
#include <wx/panel.h>
|
||||
#include "../../libslic3r/Point.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
class wxNotebook;
|
||||
class wxGLCanvas;
|
||||
class wxBoxSizer;
|
||||
class wxStaticText;
|
||||
class wxChoice;
|
||||
class wxComboCtrl;
|
||||
class wxCheckBox;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class DynamicPrintConfig;
|
||||
class Print;
|
||||
class GCodePreviewData;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class Preview : public wxPanel
|
||||
{
|
||||
wxGLCanvas* m_canvas;
|
||||
wxBoxSizer* m_double_slider_sizer;
|
||||
wxStaticText* m_label_view_type;
|
||||
wxChoice* m_choice_view_type;
|
||||
wxStaticText* m_label_show_features;
|
||||
wxComboCtrl* m_combochecklist_features;
|
||||
wxCheckBox* m_checkbox_travel;
|
||||
wxCheckBox* m_checkbox_retractions;
|
||||
wxCheckBox* m_checkbox_unretractions;
|
||||
wxCheckBox* m_checkbox_shells;
|
||||
|
||||
DynamicPrintConfig* m_config;
|
||||
Print* m_print;
|
||||
GCodePreviewData* m_gcode_preview_data;
|
||||
|
||||
unsigned int m_number_extruders;
|
||||
std::string m_preferred_color_mode;
|
||||
|
||||
bool m_loaded;
|
||||
bool m_enabled;
|
||||
bool m_force_sliders_full_range;
|
||||
|
||||
public:
|
||||
Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data);
|
||||
virtual ~Preview();
|
||||
|
||||
void register_on_viewport_changed_callback(void* callback);
|
||||
void set_number_extruders(unsigned int number_extruders);
|
||||
void reset_gcode_preview_data();
|
||||
void set_canvas_as_dirty();
|
||||
void set_enabled(bool enabled);
|
||||
void set_bed_shape(const Pointfs& shape);
|
||||
void select_view(const std::string& direction);
|
||||
void set_viewport_from_scene(wxGLCanvas* canvas);
|
||||
void set_viewport_into_scene(wxGLCanvas* canvas);
|
||||
void set_drop_target(wxDropTarget* target);
|
||||
|
||||
void load_print();
|
||||
void reload_print(bool force = false);
|
||||
void refresh_print();
|
||||
|
||||
private:
|
||||
bool init(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data);
|
||||
|
||||
void bind_event_handlers();
|
||||
void unbind_event_handlers();
|
||||
|
||||
void show_hide_ui_elements(const std::string& what);
|
||||
|
||||
void reset_sliders();
|
||||
void update_sliders();
|
||||
|
||||
void on_size(wxSizeEvent& evt);
|
||||
void on_choice_view_type(wxCommandEvent& evt);
|
||||
void on_combochecklist_features(wxCommandEvent& evt);
|
||||
void on_checkbox_travel(wxCommandEvent& evt);
|
||||
void on_checkbox_retractions(wxCommandEvent& evt);
|
||||
void on_checkbox_unretractions(wxCommandEvent& evt);
|
||||
void on_checkbox_shells(wxCommandEvent& evt);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_GUI_Preview_hpp_
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "../../libslic3r/libslic3r.h"
|
||||
#include "GUI_PreviewIface.hpp"
|
||||
#include "GUI_Preview.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
void PreviewIface::register_on_viewport_changed_callback(void* callback)
|
||||
{
|
||||
m_preview->register_on_viewport_changed_callback(callback);
|
||||
}
|
||||
|
||||
void PreviewIface::set_number_extruders(unsigned int number_extruders)
|
||||
{
|
||||
m_preview->set_number_extruders(number_extruders);
|
||||
}
|
||||
|
||||
void PreviewIface::reset_gcode_preview_data()
|
||||
{
|
||||
m_preview->reset_gcode_preview_data();
|
||||
}
|
||||
|
||||
void PreviewIface::reload_print(bool force)
|
||||
{
|
||||
m_preview->reload_print(force);
|
||||
}
|
||||
|
||||
void PreviewIface::set_canvas_as_dirty()
|
||||
{
|
||||
m_preview->set_canvas_as_dirty();
|
||||
}
|
||||
|
||||
void PreviewIface::set_enabled(bool enabled)
|
||||
{
|
||||
m_preview->set_enabled(enabled);
|
||||
}
|
||||
|
||||
void PreviewIface::set_bed_shape(const Pointfs& shape)
|
||||
{
|
||||
m_preview->set_bed_shape(shape);
|
||||
}
|
||||
|
||||
void PreviewIface::select_view(const std::string& direction)
|
||||
{
|
||||
m_preview->select_view(direction);
|
||||
}
|
||||
|
||||
void PreviewIface::set_viewport_from_scene(wxGLCanvas* canvas)
|
||||
{
|
||||
m_preview->set_viewport_from_scene(canvas);
|
||||
}
|
||||
|
||||
void PreviewIface::set_viewport_into_scene(wxGLCanvas* canvas)
|
||||
{
|
||||
m_preview->set_viewport_into_scene(canvas);
|
||||
}
|
||||
|
||||
void PreviewIface::set_drop_target(wxDropTarget* target)
|
||||
{
|
||||
m_preview->set_drop_target(target);
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef slic3r_GUI_PreviewIface_hpp_
|
||||
#define slic3r_GUI_PreviewIface_hpp_
|
||||
|
||||
#include "../../libslic3r/Point.hpp"
|
||||
|
||||
class wxGLCanvas;
|
||||
class wxDropTarget;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
class Preview;
|
||||
} // namespace GUI
|
||||
|
||||
class PreviewIface
|
||||
{
|
||||
GUI::Preview* m_preview;
|
||||
|
||||
public:
|
||||
explicit PreviewIface(GUI::Preview* preview) : m_preview(preview) {}
|
||||
|
||||
void register_on_viewport_changed_callback(void* callback);
|
||||
void set_number_extruders(unsigned int number_extruders);
|
||||
void reset_gcode_preview_data();
|
||||
void reload_print(bool force = false);
|
||||
void set_canvas_as_dirty();
|
||||
void set_enabled(bool enabled);
|
||||
void set_bed_shape(const Pointfs& shape);
|
||||
void select_view(const std::string& direction);
|
||||
void set_viewport_from_scene(wxGLCanvas* canvas);
|
||||
void set_viewport_into_scene(wxGLCanvas* canvas);
|
||||
void set_drop_target(wxDropTarget* target);
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_GUI_PreviewIface_hpp_
|
||||
@@ -69,12 +69,12 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
|
||||
field->m_on_change = [this](std::string opt_id, boost::any value){
|
||||
//! This function will be called from Field.
|
||||
//! Call OptionGroup._on_change(...)
|
||||
if (!this->m_disabled)
|
||||
if (!m_disabled)
|
||||
this->on_change_OG(opt_id, value);
|
||||
};
|
||||
field->m_on_kill_focus = [this](){
|
||||
//! This function will be called from Field.
|
||||
if (!this->m_disabled)
|
||||
if (!m_disabled)
|
||||
this->on_kill_focus();
|
||||
};
|
||||
field->m_parent = parent();
|
||||
@@ -82,7 +82,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
|
||||
//! Label to change background color, when option is modified
|
||||
field->m_Label = label;
|
||||
field->m_back_to_initial_value = [this](std::string opt_id){
|
||||
if (!this->m_disabled)
|
||||
if (!m_disabled)
|
||||
this->back_to_initial_value(opt_id);
|
||||
};
|
||||
field->m_back_to_sys_value = [this](std::string opt_id){
|
||||
|
||||
@@ -71,14 +71,6 @@ void PreferencesDialog::build()
|
||||
option = Option (def, "preset_update");
|
||||
m_optgroup->append_single_option_line(option);
|
||||
|
||||
def.label = L("Disable USB/serial connection");
|
||||
def.type = coBool;
|
||||
def.tooltip = L("Disable communication with the printer over a serial / USB cable. "
|
||||
"This simplifies the user interface in case the printer is never attached to the computer.");
|
||||
def.default_value = new ConfigOptionBool{ app_config->get("no_controller")[0] == '1' }; // 1;
|
||||
option = Option (def,"no_controller");
|
||||
m_optgroup->append_single_option_line(option);
|
||||
|
||||
def.label = L("Suppress \" - default - \" presets");
|
||||
def.type = coBool;
|
||||
def.tooltip = L("Suppress \" - default - \" presets in the Print / Filament / Printer "
|
||||
@@ -118,8 +110,7 @@ void PreferencesDialog::build()
|
||||
|
||||
void PreferencesDialog::accept()
|
||||
{
|
||||
if (m_values.find("no_controller") != m_values.end()||
|
||||
m_values.find("no_defaults") != m_values.end()||
|
||||
if (m_values.find("no_defaults") != m_values.end()||
|
||||
m_values.find("use_legacy_opengl")!= m_values.end()) {
|
||||
warning_catcher(this, _(L("You need to restart Slic3r to make the changes effective.")));
|
||||
}
|
||||
|
||||
@@ -691,7 +691,7 @@ size_t PresetCollection::first_visible_idx() const
|
||||
for (; idx < this->m_presets.size(); ++ idx)
|
||||
if (m_presets[idx].is_visible)
|
||||
break;
|
||||
if (idx == this->m_presets.size())
|
||||
if (idx == m_presets.size())
|
||||
idx = 0;
|
||||
return idx;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef IPROGRESSINDICATOR_HPP
|
||||
#define IPROGRESSINDICATOR_HPP
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
/**
|
||||
* @brief Generic progress indication interface.
|
||||
*/
|
||||
class ProgressIndicator {
|
||||
public:
|
||||
using CancelFn = std::function<void(void)>; // Cancel function signature.
|
||||
|
||||
private:
|
||||
float m_state = .0f, m_max = 1.f, m_step;
|
||||
CancelFn m_cancelfunc = [](){};
|
||||
|
||||
public:
|
||||
|
||||
inline virtual ~ProgressIndicator() {}
|
||||
|
||||
/// Get the maximum of the progress range.
|
||||
float max() const { return m_max; }
|
||||
|
||||
/// Get the current progress state
|
||||
float state() const { return m_state; }
|
||||
|
||||
/// Set the maximum of the progress range
|
||||
virtual void max(float maxval) { m_max = maxval; }
|
||||
|
||||
/// Set the current state of the progress.
|
||||
virtual void state(float val) { m_state = val; }
|
||||
|
||||
/**
|
||||
* @brief Number of states int the progress. Can be used instead of giving a
|
||||
* maximum value.
|
||||
*/
|
||||
virtual void states(unsigned statenum) {
|
||||
m_step = m_max / statenum;
|
||||
}
|
||||
|
||||
/// Message shown on the next status update.
|
||||
virtual void message(const std::string&) = 0;
|
||||
|
||||
/// Title of the operation.
|
||||
virtual void title(const std::string&) = 0;
|
||||
|
||||
/// Formatted message for the next status update. Works just like sprintf.
|
||||
virtual void message_fmt(const std::string& fmt, ...);
|
||||
|
||||
/// Set up a cancel callback for the operation if feasible.
|
||||
virtual void on_cancel(CancelFn func = CancelFn()) { m_cancelfunc = func; }
|
||||
|
||||
/**
|
||||
* Explicitly shut down the progress indicator and call the associated
|
||||
* callback.
|
||||
*/
|
||||
virtual void cancel() { m_cancelfunc(); }
|
||||
|
||||
/// Convenience function to call message and status update in one function.
|
||||
void update(float st, const std::string& msg) {
|
||||
message(msg); state(st);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // IPROGRESSINDICATOR_HPP
|
||||
@@ -14,116 +14,117 @@ namespace Slic3r {
|
||||
ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id):
|
||||
self(new wxStatusBar(parent ? parent : GUI::get_main_frame(),
|
||||
id == -1? wxID_ANY : id)),
|
||||
timer_(new wxTimer(self)),
|
||||
prog_ (new wxGauge(self,
|
||||
m_timer(new wxTimer(self)),
|
||||
m_prog (new wxGauge(self,
|
||||
wxGA_HORIZONTAL,
|
||||
100,
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize)),
|
||||
cancelbutton_(new wxButton(self,
|
||||
m_cancelbutton(new wxButton(self,
|
||||
-1,
|
||||
"Cancel",
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize))
|
||||
{
|
||||
prog_->Hide();
|
||||
cancelbutton_->Hide();
|
||||
m_prog->Hide();
|
||||
m_cancelbutton->Hide();
|
||||
|
||||
self->SetFieldsCount(3);
|
||||
int w[] = {-1, 150, 155};
|
||||
self->SetStatusWidths(3, w);
|
||||
|
||||
self->Bind(wxEVT_TIMER, [this](const wxTimerEvent&) {
|
||||
if (prog_->IsShown()) timer_->Stop();
|
||||
if(is_busy()) prog_->Pulse();
|
||||
if (m_prog->IsShown()) m_timer->Stop();
|
||||
if(is_busy()) m_prog->Pulse();
|
||||
});
|
||||
|
||||
self->Bind(wxEVT_SIZE, [this](wxSizeEvent& event){
|
||||
wxRect rect;
|
||||
self->GetFieldRect(1, rect);
|
||||
auto offset = 0;
|
||||
cancelbutton_->Move(rect.GetX() + offset, rect.GetY() + offset);
|
||||
cancelbutton_->SetSize(rect.GetWidth() - offset, rect.GetHeight());
|
||||
m_cancelbutton->Move(rect.GetX() + offset, rect.GetY() + offset);
|
||||
m_cancelbutton->SetSize(rect.GetWidth() - offset, rect.GetHeight());
|
||||
|
||||
self->GetFieldRect(2, rect);
|
||||
prog_->Move(rect.GetX() + offset, rect.GetY() + offset);
|
||||
prog_->SetSize(rect.GetWidth() - offset, rect.GetHeight());
|
||||
m_prog->Move(rect.GetX() + offset, rect.GetY() + offset);
|
||||
m_prog->SetSize(rect.GetWidth() - offset, rect.GetHeight());
|
||||
|
||||
event.Skip();
|
||||
});
|
||||
|
||||
cancelbutton_->Bind(wxEVT_BUTTON, [this](const wxCommandEvent&) {
|
||||
if(cancel_cb_) cancel_cb_();
|
||||
cancelbutton_->Hide();
|
||||
m_cancelbutton->Bind(wxEVT_BUTTON, [this](const wxCommandEvent&) {
|
||||
if(m_cancel_cb) m_cancel_cb();
|
||||
m_perl_cancel_callback.call();
|
||||
m_cancelbutton->Hide();
|
||||
});
|
||||
}
|
||||
|
||||
ProgressStatusBar::~ProgressStatusBar() {
|
||||
if(timer_->IsRunning()) timer_->Stop();
|
||||
if(m_timer->IsRunning()) m_timer->Stop();
|
||||
}
|
||||
|
||||
int ProgressStatusBar::get_progress() const
|
||||
{
|
||||
return prog_->GetValue();
|
||||
return m_prog->GetValue();
|
||||
}
|
||||
|
||||
void ProgressStatusBar::set_progress(int val)
|
||||
{
|
||||
if(!prog_->IsShown()) show_progress(true);
|
||||
if(!m_prog->IsShown()) show_progress(true);
|
||||
|
||||
if(val == prog_->GetRange()) {
|
||||
prog_->SetValue(0);
|
||||
if(val == m_prog->GetRange()) {
|
||||
m_prog->SetValue(0);
|
||||
show_progress(false);
|
||||
} else {
|
||||
prog_->SetValue(val);
|
||||
m_prog->SetValue(val);
|
||||
}
|
||||
}
|
||||
|
||||
int ProgressStatusBar::get_range() const
|
||||
{
|
||||
return prog_->GetRange();
|
||||
return m_prog->GetRange();
|
||||
}
|
||||
|
||||
void ProgressStatusBar::set_range(int val)
|
||||
{
|
||||
if(val != prog_->GetRange()) {
|
||||
prog_->SetRange(val);
|
||||
if(val != m_prog->GetRange()) {
|
||||
m_prog->SetRange(val);
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressStatusBar::show_progress(bool show)
|
||||
{
|
||||
prog_->Show(show);
|
||||
prog_->Pulse();
|
||||
m_prog->Show(show);
|
||||
m_prog->Pulse();
|
||||
}
|
||||
|
||||
void ProgressStatusBar::start_busy(int rate)
|
||||
{
|
||||
busy_ = true;
|
||||
m_busy = true;
|
||||
show_progress(true);
|
||||
if (!timer_->IsRunning()) {
|
||||
timer_->Start(rate);
|
||||
if (!m_timer->IsRunning()) {
|
||||
m_timer->Start(rate);
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressStatusBar::stop_busy()
|
||||
{
|
||||
timer_->Stop();
|
||||
m_timer->Stop();
|
||||
show_progress(false);
|
||||
prog_->SetValue(0);
|
||||
busy_ = false;
|
||||
m_prog->SetValue(0);
|
||||
m_busy = false;
|
||||
}
|
||||
|
||||
void ProgressStatusBar::set_cancel_callback(ProgressStatusBar::CancelFn ccb) {
|
||||
cancel_cb_ = ccb;
|
||||
if(ccb) cancelbutton_->Show();
|
||||
else cancelbutton_->Hide();
|
||||
m_cancel_cb = ccb;
|
||||
if(ccb) m_cancelbutton->Show();
|
||||
else m_cancelbutton->Hide();
|
||||
}
|
||||
|
||||
void ProgressStatusBar::run(int rate)
|
||||
{
|
||||
if(!timer_->IsRunning()) {
|
||||
timer_->Start(rate);
|
||||
if(!m_timer->IsRunning()) {
|
||||
m_timer->Start(rate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,19 +134,19 @@ void ProgressStatusBar::embed(wxFrame *frame)
|
||||
mf->SetStatusBar(self);
|
||||
}
|
||||
|
||||
void ProgressStatusBar::set_status_text(const std::string& txt)
|
||||
void ProgressStatusBar::set_status_text(const wxString& txt)
|
||||
{
|
||||
self->SetStatusText(txt);
|
||||
self->SetStatusText(wxString::FromUTF8(txt.c_str()));
|
||||
}
|
||||
|
||||
void ProgressStatusBar::show_cancel_button()
|
||||
{
|
||||
cancelbutton_->Show();
|
||||
m_cancelbutton->Show();
|
||||
}
|
||||
|
||||
void ProgressStatusBar::hide_cancel_button()
|
||||
{
|
||||
cancelbutton_->Hide();
|
||||
m_cancelbutton->Hide();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
#include "../../callback.hpp"
|
||||
|
||||
class wxTimer;
|
||||
class wxGauge;
|
||||
class wxButton;
|
||||
@@ -11,6 +13,7 @@ class wxTimerEvent;
|
||||
class wxStatusBar;
|
||||
class wxWindow;
|
||||
class wxFrame;
|
||||
class wxString;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@@ -21,9 +24,9 @@ namespace Slic3r {
|
||||
*/
|
||||
class ProgressStatusBar {
|
||||
wxStatusBar *self; // we cheat! It should be the base class but: perl!
|
||||
wxTimer *timer_;
|
||||
wxGauge *prog_;
|
||||
wxButton *cancelbutton_;
|
||||
wxTimer *m_timer;
|
||||
wxGauge *m_prog;
|
||||
wxButton *m_cancelbutton;
|
||||
public:
|
||||
|
||||
/// Cancel callback function type
|
||||
@@ -39,20 +42,21 @@ public:
|
||||
void show_progress(bool);
|
||||
void start_busy(int = 100);
|
||||
void stop_busy();
|
||||
inline bool is_busy() const { return busy_; }
|
||||
inline bool is_busy() const { return m_busy; }
|
||||
void set_cancel_callback(CancelFn = CancelFn());
|
||||
inline void remove_cancel_callback() { set_cancel_callback(); }
|
||||
void run(int rate);
|
||||
void embed(wxFrame *frame = nullptr);
|
||||
void set_status_text(const std::string& txt);
|
||||
void set_status_text(const wxString& txt);
|
||||
|
||||
// Temporary methods to satisfy Perl side
|
||||
void show_cancel_button();
|
||||
void hide_cancel_button();
|
||||
|
||||
PerlCallback m_perl_cancel_callback;
|
||||
private:
|
||||
bool busy_ = false;
|
||||
CancelFn cancel_cb_;
|
||||
bool m_busy = false;
|
||||
CancelFn m_cancel_cb;
|
||||
};
|
||||
|
||||
namespace GUI {
|
||||
|
||||
@@ -1531,6 +1531,7 @@ void TabPrinter::build_fff()
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
if (!m_no_controller)
|
||||
{
|
||||
optgroup = page->new_optgroup(_(L("USB/Serial connection")));
|
||||
@@ -1575,6 +1576,7 @@ void TabPrinter::build_fff()
|
||||
line.append_widget(serial_test);
|
||||
optgroup->append_line(line);
|
||||
}
|
||||
#endif
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Printer Host upload")));
|
||||
|
||||
@@ -1748,8 +1750,10 @@ void TabPrinter::build_fff()
|
||||
|
||||
build_extruder_pages();
|
||||
|
||||
#if 0
|
||||
if (!m_no_controller)
|
||||
update_serial_ports();
|
||||
#endif
|
||||
}
|
||||
|
||||
void TabPrinter::build_sla()
|
||||
|
||||
@@ -170,7 +170,6 @@ protected:
|
||||
std::vector<PageShp> m_pages;
|
||||
bool m_disable_tree_sel_changed_event;
|
||||
bool m_show_incompatible_presets;
|
||||
bool m_no_controller;
|
||||
|
||||
std::vector<std::string> m_reload_dependent_tabs = {};
|
||||
enum OptStatus { osSystemValue = 1, osInitValue = 2 };
|
||||
@@ -199,8 +198,8 @@ public:
|
||||
|
||||
public:
|
||||
Tab() {}
|
||||
Tab(wxNotebook* parent, const wxString& title, const char* name, bool no_controller) :
|
||||
m_parent(parent), m_title(title), m_name(name), m_no_controller(no_controller) {
|
||||
Tab(wxNotebook* parent, const wxString& title, const char* name) :
|
||||
m_parent(parent), m_title(title), m_name(name) {
|
||||
Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL, name);
|
||||
get_tabs_list().push_back(this);
|
||||
}
|
||||
@@ -282,8 +281,8 @@ class TabPrint : public Tab
|
||||
{
|
||||
public:
|
||||
TabPrint() {}
|
||||
TabPrint(wxNotebook* parent, bool no_controller) :
|
||||
Tab(parent, _(L("Print Settings")), "print", no_controller) {}
|
||||
TabPrint(wxNotebook* parent) :
|
||||
Tab(parent, _(L("Print Settings")), "print") {}
|
||||
~TabPrint(){}
|
||||
|
||||
ogStaticText* m_recommended_thin_wall_thickness_description_line;
|
||||
@@ -302,8 +301,8 @@ class TabFilament : public Tab
|
||||
ogStaticText* m_cooling_description_line;
|
||||
public:
|
||||
TabFilament() {}
|
||||
TabFilament(wxNotebook* parent, bool no_controller) :
|
||||
Tab(parent, _(L("Filament Settings")), "filament", no_controller) {}
|
||||
TabFilament(wxNotebook* parent) :
|
||||
Tab(parent, _(L("Filament Settings")), "filament") {}
|
||||
~TabFilament(){}
|
||||
|
||||
void build() override;
|
||||
@@ -335,7 +334,7 @@ public:
|
||||
PrinterTechnology m_printer_technology = ptFFF;
|
||||
|
||||
TabPrinter() {}
|
||||
TabPrinter(wxNotebook* parent, bool no_controller) : Tab(parent, _(L("Printer Settings")), "printer", no_controller) {}
|
||||
TabPrinter(wxNotebook* parent) : Tab(parent, _(L("Printer Settings")), "printer") {}
|
||||
~TabPrinter(){}
|
||||
|
||||
void build() override;
|
||||
@@ -357,8 +356,8 @@ class TabSLAMaterial : public Tab
|
||||
{
|
||||
public:
|
||||
TabSLAMaterial() {}
|
||||
TabSLAMaterial(wxNotebook* parent, bool no_controller) :
|
||||
Tab(parent, _(L("SLA Material Settings")), "sla_material", no_controller) {}
|
||||
TabSLAMaterial(wxNotebook* parent) :
|
||||
Tab(parent, _(L("SLA Material Settings")), "sla_material") {}
|
||||
~TabSLAMaterial(){}
|
||||
|
||||
void build() override;
|
||||
|
||||
Reference in New Issue
Block a user