mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-23 08:41:11 -06:00
Faster gizmos update
This commit is contained in:
commit
550f6e307f
40 changed files with 1415 additions and 753 deletions
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "3DScene.hpp"
|
||||
|
||||
#include "../../libslic3r/libslic3r.h"
|
||||
#include "../../libslic3r/ExtrusionEntity.hpp"
|
||||
#include "../../libslic3r/ExtrusionEntityCollection.hpp"
|
||||
#include "../../libslic3r/Geometry.hpp"
|
||||
|
@ -28,8 +27,15 @@
|
|||
#include <wx/image.h>
|
||||
#include <wx/settings.h>
|
||||
|
||||
#include <Eigen/Dense>
|
||||
|
||||
#include "GUI.hpp"
|
||||
|
||||
static const float UNIT_MATRIX[] = { 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh)
|
||||
|
@ -198,6 +204,34 @@ const float GLVolume::HOVER_COLOR[4] = { 0.4f, 0.9f, 0.1f, 1.0f };
|
|||
const float GLVolume::OUTSIDE_COLOR[4] = { 0.0f, 0.38f, 0.8f, 1.0f };
|
||||
const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f };
|
||||
|
||||
GLVolume::GLVolume(float r, float g, float b, float a)
|
||||
: m_angle_z(0.0f)
|
||||
, m_scale_factor(1.0f)
|
||||
, m_dirty(true)
|
||||
, composite_id(-1)
|
||||
, select_group_id(-1)
|
||||
, drag_group_id(-1)
|
||||
, extruder_id(0)
|
||||
, selected(false)
|
||||
, is_active(true)
|
||||
, zoom_to_volumes(true)
|
||||
, outside_printer_detection_enabled(true)
|
||||
, is_outside(false)
|
||||
, hover(false)
|
||||
, is_modifier(false)
|
||||
, is_wipe_tower(false)
|
||||
, tverts_range(0, size_t(-1))
|
||||
, qverts_range(0, size_t(-1))
|
||||
{
|
||||
m_world_mat = std::vector<float>(UNIT_MATRIX, std::end(UNIT_MATRIX));
|
||||
|
||||
color[0] = r;
|
||||
color[1] = g;
|
||||
color[2] = b;
|
||||
color[3] = a;
|
||||
set_render_color(r, g, b, a);
|
||||
}
|
||||
|
||||
void GLVolume::set_render_color(float r, float g, float b, float a)
|
||||
{
|
||||
render_color[0] = r;
|
||||
|
@ -218,12 +252,7 @@ void GLVolume::set_render_color(const float* rgba, unsigned int size)
|
|||
void GLVolume::set_render_color()
|
||||
{
|
||||
if (selected)
|
||||
{
|
||||
if (is_outside)
|
||||
set_render_color(SELECTED_OUTSIDE_COLOR, 4);
|
||||
else
|
||||
set_render_color(SELECTED_COLOR, 4);
|
||||
}
|
||||
set_render_color(is_outside ? SELECTED_OUTSIDE_COLOR : SELECTED_COLOR, 4);
|
||||
else if (hover)
|
||||
set_render_color(HOVER_COLOR, 4);
|
||||
else if (is_outside)
|
||||
|
@ -232,6 +261,52 @@ void GLVolume::set_render_color()
|
|||
set_render_color(color, 4);
|
||||
}
|
||||
|
||||
const Pointf3& GLVolume::get_origin() const
|
||||
{
|
||||
return m_origin;
|
||||
}
|
||||
|
||||
void GLVolume::set_origin(const Pointf3& origin)
|
||||
{
|
||||
m_origin = origin;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void GLVolume::set_angle_z(float angle_z)
|
||||
{
|
||||
m_angle_z = angle_z;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
void GLVolume::set_scale_factor(float scale_factor)
|
||||
{
|
||||
m_scale_factor = scale_factor;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
const std::vector<float>& GLVolume::world_matrix() const
|
||||
{
|
||||
if (m_dirty)
|
||||
{
|
||||
Eigen::Transform<float, 3, Eigen::Affine> m = Eigen::Transform<float, 3, Eigen::Affine>::Identity();
|
||||
m.translate(Eigen::Vector3f((float)m_origin.x, (float)m_origin.y, (float)m_origin.z));
|
||||
m.rotate(Eigen::AngleAxisf(m_angle_z, Eigen::Vector3f::UnitZ()));
|
||||
m.scale(m_scale_factor);
|
||||
::memcpy((void*)m_world_mat.data(), (const void*)m.data(), 16 * sizeof(float));
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
return m_world_mat;
|
||||
}
|
||||
|
||||
BoundingBoxf3 GLVolume::transformed_bounding_box() const
|
||||
{
|
||||
if (m_dirty)
|
||||
m_transformed_bounding_box = bounding_box.transformed(world_matrix());
|
||||
|
||||
return m_transformed_bounding_box;
|
||||
}
|
||||
|
||||
void GLVolume::set_range(double min_z, double max_z)
|
||||
{
|
||||
this->qverts_range.first = 0;
|
||||
|
@ -272,14 +347,16 @@ void GLVolume::render() const
|
|||
if (!is_active)
|
||||
return;
|
||||
|
||||
glCullFace(GL_BACK);
|
||||
glPushMatrix();
|
||||
glTranslated(this->origin.x, this->origin.y, this->origin.z);
|
||||
::glCullFace(GL_BACK);
|
||||
::glPushMatrix();
|
||||
::glTranslated(m_origin.x, m_origin.y, m_origin.z);
|
||||
::glRotatef(m_angle_z * 180.0f / PI, 0.0f, 0.0f, 1.0f);
|
||||
::glScalef(m_scale_factor, m_scale_factor, m_scale_factor);
|
||||
if (this->indexed_vertex_array.indexed())
|
||||
this->indexed_vertex_array.render(this->tverts_range, this->qverts_range);
|
||||
else
|
||||
this->indexed_vertex_array.render();
|
||||
glPopMatrix();
|
||||
::glPopMatrix();
|
||||
}
|
||||
|
||||
void GLVolume::render_using_layer_height() const
|
||||
|
@ -297,6 +374,7 @@ void GLVolume::render_using_layer_height() const
|
|||
GLint z_texture_row_to_normalized_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "z_texture_row_to_normalized") : -1;
|
||||
GLint z_cursor_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "z_cursor") : -1;
|
||||
GLint z_cursor_band_width_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "z_cursor_band_width") : -1;
|
||||
GLint world_matrix_id = (layer_height_texture_data.shader_id > 0) ? glGetUniformLocation(layer_height_texture_data.shader_id, "volume_world_matrix") : -1;
|
||||
|
||||
if (z_to_texture_row_id >= 0)
|
||||
glUniform1f(z_to_texture_row_id, (GLfloat)layer_height_texture_z_to_row_id());
|
||||
|
@ -310,14 +388,19 @@ void GLVolume::render_using_layer_height() const
|
|||
if (z_cursor_band_width_id >= 0)
|
||||
glUniform1f(z_cursor_band_width_id, (GLfloat)layer_height_texture_data.edit_band_width);
|
||||
|
||||
unsigned int w = layer_height_texture_width();
|
||||
unsigned int h = layer_height_texture_height();
|
||||
if (world_matrix_id >= 0)
|
||||
::glUniformMatrix4fv(world_matrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data());
|
||||
|
||||
GLsizei w = (GLsizei)layer_height_texture_width();
|
||||
GLsizei h = (GLsizei)layer_height_texture_height();
|
||||
GLsizei half_w = w / 2;
|
||||
GLsizei half_h = h / 2;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, layer_height_texture_data.texture_id);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, w / 2, h / 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, half_w, half_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, layer_height_texture_data_ptr_level0());
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, w / 2, h / 2, GL_RGBA, GL_UNSIGNED_BYTE, layer_height_texture_data_ptr_level1());
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, layer_height_texture_data_ptr_level1());
|
||||
|
||||
render();
|
||||
|
||||
|
@ -327,6 +410,128 @@ void GLVolume::render_using_layer_height() const
|
|||
glUseProgram(current_program_id);
|
||||
}
|
||||
|
||||
void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) const
|
||||
{
|
||||
if (!is_active)
|
||||
return;
|
||||
|
||||
if (!indexed_vertex_array.vertices_and_normals_interleaved_VBO_id)
|
||||
return;
|
||||
|
||||
if (layer_height_texture_data.can_use())
|
||||
{
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
::glDisableClientState(GL_NORMAL_ARRAY);
|
||||
render_using_layer_height();
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_NORMAL_ARRAY);
|
||||
return;
|
||||
}
|
||||
|
||||
GLsizei n_triangles = GLsizei(std::min(indexed_vertex_array.triangle_indices_size, tverts_range.second - tverts_range.first));
|
||||
GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first));
|
||||
if (n_triangles + n_quads == 0)
|
||||
{
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
::glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if (color_id >= 0)
|
||||
{
|
||||
float color[4];
|
||||
::memcpy((void*)color, (const void*)render_color, 4 * sizeof(float));
|
||||
::glUniform4fv(color_id, 1, (const GLfloat*)color);
|
||||
}
|
||||
else
|
||||
::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]);
|
||||
|
||||
if (detection_id != -1)
|
||||
::glUniform1i(detection_id, outside_printer_detection_enabled ? 1 : 0);
|
||||
|
||||
if (worldmatrix_id != -1)
|
||||
::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data());
|
||||
|
||||
render();
|
||||
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (color_id >= 0)
|
||||
::glUniform4fv(color_id, 1, (const GLfloat*)render_color);
|
||||
else
|
||||
::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]);
|
||||
|
||||
if (detection_id != -1)
|
||||
::glUniform1i(detection_id, outside_printer_detection_enabled ? 1 : 0);
|
||||
|
||||
if (worldmatrix_id != -1)
|
||||
::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data());
|
||||
|
||||
::glBindBuffer(GL_ARRAY_BUFFER, indexed_vertex_array.vertices_and_normals_interleaved_VBO_id);
|
||||
::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)));
|
||||
::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr);
|
||||
|
||||
::glPushMatrix();
|
||||
::glTranslated(m_origin.x, m_origin.y, m_origin.z);
|
||||
::glRotatef(m_angle_z * 180.0f / PI, 0.0f, 0.0f, 1.0f);
|
||||
::glScalef(m_scale_factor, m_scale_factor, m_scale_factor);
|
||||
|
||||
if (n_triangles > 0)
|
||||
{
|
||||
::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.triangle_indices_VBO_id);
|
||||
::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, (const void*)(tverts_range.first * 4));
|
||||
}
|
||||
if (n_quads > 0)
|
||||
{
|
||||
::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexed_vertex_array.quad_indices_VBO_id);
|
||||
::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, (const void*)(qverts_range.first * 4));
|
||||
}
|
||||
|
||||
::glPopMatrix();
|
||||
}
|
||||
|
||||
void GLVolume::render_legacy() const
|
||||
{
|
||||
assert(!indexed_vertex_array.vertices_and_normals_interleaved_VBO_id);
|
||||
if (!is_active)
|
||||
return;
|
||||
|
||||
GLsizei n_triangles = GLsizei(std::min(indexed_vertex_array.triangle_indices_size, tverts_range.second - tverts_range.first));
|
||||
GLsizei n_quads = GLsizei(std::min(indexed_vertex_array.quad_indices_size, qverts_range.second - qverts_range.first));
|
||||
if (n_triangles + n_quads == 0)
|
||||
{
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
::glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]);
|
||||
render();
|
||||
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]);
|
||||
::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data() + 3);
|
||||
::glNormalPointer(GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data());
|
||||
|
||||
::glPushMatrix();
|
||||
::glTranslated(m_origin.x, m_origin.y, m_origin.z);
|
||||
::glRotatef(m_angle_z * 180.0f / PI, 0.0f, 0.0f, 1.0f);
|
||||
::glScalef(m_scale_factor, m_scale_factor, m_scale_factor);
|
||||
|
||||
if (n_triangles > 0)
|
||||
::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, indexed_vertex_array.triangle_indices.data() + tverts_range.first);
|
||||
|
||||
if (n_quads > 0)
|
||||
::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, indexed_vertex_array.quad_indices.data() + qverts_range.first);
|
||||
|
||||
::glPopMatrix();
|
||||
}
|
||||
|
||||
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.z);
|
||||
|
@ -399,7 +604,6 @@ std::vector<int> GLVolumeCollection::load_object(
|
|||
for (int instance_idx : instance_idxs) {
|
||||
const ModelInstance *instance = model_object->instances[instance_idx];
|
||||
TriangleMesh mesh = model_volume->mesh;
|
||||
instance->transform_mesh(&mesh);
|
||||
volumes_idx.push_back(int(this->volumes.size()));
|
||||
float color[4];
|
||||
memcpy(color, colors[((color_by == "volume") ? volume_idx : obj_idx) % 4], sizeof(float) * 3);
|
||||
|
@ -433,13 +637,15 @@ std::vector<int> GLVolumeCollection::load_object(
|
|||
v.extruder_id = extruder_id;
|
||||
}
|
||||
v.is_modifier = model_volume->modifier;
|
||||
v.set_origin(Pointf3(instance->offset.x, instance->offset.y, 0.0));
|
||||
v.set_angle_z(instance->rotation);
|
||||
v.set_scale_factor(instance->scaling_factor);
|
||||
}
|
||||
}
|
||||
|
||||
return volumes_idx;
|
||||
}
|
||||
|
||||
|
||||
int GLVolumeCollection::load_wipe_tower_preview(
|
||||
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs)
|
||||
{
|
||||
|
@ -460,7 +666,8 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
|||
else
|
||||
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
|
||||
|
||||
v.origin = Pointf3(pos_x, pos_y, 0.);
|
||||
v.set_origin(Pointf3(pos_x, pos_y, 0.));
|
||||
|
||||
// finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
|
||||
v.bounding_box = v.indexed_vertex_array.bounding_box();
|
||||
v.indexed_vertex_array.finalize_geometry(use_VBOs);
|
||||
|
@ -485,102 +692,23 @@ void GLVolumeCollection::render_VBOs() const
|
|||
GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1;
|
||||
GLint print_box_min_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.min") : -1;
|
||||
GLint print_box_max_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.max") : -1;
|
||||
GLint print_box_origin_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.volume_origin") : -1;
|
||||
GLint print_box_detection_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.volume_detection") : -1;
|
||||
GLint print_box_worldmatrix_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.volume_world_matrix") : -1;
|
||||
|
||||
for (GLVolume *volume : this->volumes) {
|
||||
if (!volume->is_active)
|
||||
continue;
|
||||
if (print_box_min_id != -1)
|
||||
::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min);
|
||||
|
||||
if (!volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id)
|
||||
continue;
|
||||
if (print_box_max_id != -1)
|
||||
::glUniform3fv(print_box_max_id, 1, (const GLfloat*)print_box_max);
|
||||
|
||||
for (GLVolume *volume : this->volumes)
|
||||
{
|
||||
if (volume->layer_height_texture_data.can_use())
|
||||
{
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
::glDisableClientState(GL_NORMAL_ARRAY);
|
||||
volume->generate_layer_height_texture(volume->layer_height_texture_data.print_object, false);
|
||||
volume->render_using_layer_height();
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_NORMAL_ARRAY);
|
||||
continue;
|
||||
}
|
||||
|
||||
volume->set_render_color();
|
||||
|
||||
GLsizei n_triangles = GLsizei(std::min(volume->indexed_vertex_array.triangle_indices_size, volume->tverts_range.second - volume->tverts_range.first));
|
||||
GLsizei n_quads = GLsizei(std::min(volume->indexed_vertex_array.quad_indices_size, volume->qverts_range.second - volume->qverts_range.first));
|
||||
if (n_triangles + n_quads == 0)
|
||||
{
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
::glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if (color_id >= 0)
|
||||
{
|
||||
float color[4];
|
||||
::memcpy((void*)color, (const void*)volume->render_color, 4 * sizeof(float));
|
||||
::glUniform4fv(color_id, 1, (const GLfloat*)color);
|
||||
}
|
||||
else
|
||||
::glColor4f(volume->render_color[0], volume->render_color[1], volume->render_color[2], volume->render_color[3]);
|
||||
|
||||
if (print_box_min_id != -1)
|
||||
::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min);
|
||||
|
||||
if (print_box_max_id != -1)
|
||||
::glUniform3fv(print_box_max_id, 1, (const GLfloat*)print_box_max);
|
||||
|
||||
if (print_box_origin_id != -1)
|
||||
{
|
||||
float origin[4] = { (float)volume->origin.x, (float)volume->origin.y, (float)volume->origin.z, volume->outside_printer_detection_enabled ? 1.0f : 0.0f };
|
||||
::glUniform4fv(print_box_origin_id, 1, (const GLfloat*)origin);
|
||||
}
|
||||
|
||||
volume->render();
|
||||
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (color_id >= 0)
|
||||
::glUniform4fv(color_id, 1, (const GLfloat*)volume->render_color);
|
||||
else
|
||||
::glColor4f(volume->render_color[0], volume->render_color[1], volume->render_color[2], volume->render_color[3]);
|
||||
volume->set_render_color();
|
||||
|
||||
if (print_box_min_id != -1)
|
||||
::glUniform3fv(print_box_min_id, 1, (const GLfloat*)print_box_min);
|
||||
|
||||
if (print_box_max_id != -1)
|
||||
::glUniform3fv(print_box_max_id, 1, (const GLfloat*)print_box_max);
|
||||
|
||||
if (print_box_origin_id != -1)
|
||||
{
|
||||
float origin[4] = { (float)volume->origin.x, (float)volume->origin.y, (float)volume->origin.z, volume->outside_printer_detection_enabled ? 1.0f : 0.0f };
|
||||
::glUniform4fv(print_box_origin_id, 1, (const GLfloat*)origin);
|
||||
}
|
||||
|
||||
::glBindBuffer(GL_ARRAY_BUFFER, volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id);
|
||||
::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)));
|
||||
::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr);
|
||||
|
||||
bool has_offset = (volume->origin.x != 0) || (volume->origin.y != 0) || (volume->origin.z != 0);
|
||||
if (has_offset) {
|
||||
::glPushMatrix();
|
||||
::glTranslated(volume->origin.x, volume->origin.y, volume->origin.z);
|
||||
}
|
||||
|
||||
if (n_triangles > 0) {
|
||||
::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.triangle_indices_VBO_id);
|
||||
::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, (const void*)(volume->tverts_range.first * 4));
|
||||
}
|
||||
if (n_quads > 0) {
|
||||
::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.quad_indices_VBO_id);
|
||||
::glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, (const void*)(volume->qverts_range.first * 4));
|
||||
}
|
||||
|
||||
if (has_offset)
|
||||
::glPopMatrix();
|
||||
volume->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id);
|
||||
}
|
||||
|
||||
::glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
@ -601,43 +729,10 @@ void GLVolumeCollection::render_legacy() const
|
|||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
for (GLVolume *volume : this->volumes) {
|
||||
assert(! volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id);
|
||||
if (!volume->is_active)
|
||||
continue;
|
||||
|
||||
for (GLVolume *volume : this->volumes)
|
||||
{
|
||||
volume->set_render_color();
|
||||
|
||||
GLsizei n_triangles = GLsizei(std::min(volume->indexed_vertex_array.triangle_indices_size, volume->tverts_range.second - volume->tverts_range.first));
|
||||
GLsizei n_quads = GLsizei(std::min(volume->indexed_vertex_array.quad_indices_size, volume->qverts_range.second - volume->qverts_range.first));
|
||||
if (n_triangles + n_quads == 0)
|
||||
{
|
||||
::glDisableClientState(GL_VERTEX_ARRAY);
|
||||
::glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
::glColor4f(volume->render_color[0], volume->render_color[1], volume->render_color[2], volume->render_color[3]);
|
||||
volume->render();
|
||||
|
||||
::glEnableClientState(GL_VERTEX_ARRAY);
|
||||
::glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
glColor4f(volume->render_color[0], volume->render_color[1], volume->render_color[2], volume->render_color[3]);
|
||||
glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), volume->indexed_vertex_array.vertices_and_normals_interleaved.data() + 3);
|
||||
glNormalPointer(GL_FLOAT, 6 * sizeof(float), volume->indexed_vertex_array.vertices_and_normals_interleaved.data());
|
||||
bool has_offset = volume->origin.x != 0 || volume->origin.y != 0 || volume->origin.z != 0;
|
||||
if (has_offset) {
|
||||
glPushMatrix();
|
||||
glTranslated(volume->origin.x, volume->origin.y, volume->origin.z);
|
||||
}
|
||||
if (n_triangles > 0)
|
||||
glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, volume->indexed_vertex_array.triangle_indices.data() + volume->tverts_range.first);
|
||||
if (n_quads > 0)
|
||||
glDrawElements(GL_QUADS, n_quads, GL_UNSIGNED_INT, volume->indexed_vertex_array.quad_indices.data() + volume->qverts_range.first);
|
||||
if (has_offset)
|
||||
glPopMatrix();
|
||||
volume->render_legacy();
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
|
|
@ -240,7 +240,7 @@ class GLVolume {
|
|||
edit_band_width = 0.0f;
|
||||
}
|
||||
|
||||
bool can_use() { return (texture_id > 0) && (shader_id > 0) && (print_object != nullptr); }
|
||||
bool can_use() const { return (texture_id > 0) && (shader_id > 0) && (print_object != nullptr); }
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -249,44 +249,27 @@ public:
|
|||
static const float OUTSIDE_COLOR[4];
|
||||
static const float SELECTED_OUTSIDE_COLOR[4];
|
||||
|
||||
GLVolume(float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f) :
|
||||
composite_id(-1),
|
||||
select_group_id(-1),
|
||||
drag_group_id(-1),
|
||||
extruder_id(0),
|
||||
selected(false),
|
||||
is_active(true),
|
||||
zoom_to_volumes(true),
|
||||
outside_printer_detection_enabled(true),
|
||||
is_outside(false),
|
||||
hover(false),
|
||||
is_modifier(false),
|
||||
is_wipe_tower(false),
|
||||
tverts_range(0, size_t(-1)),
|
||||
qverts_range(0, size_t(-1))
|
||||
{
|
||||
color[0] = r;
|
||||
color[1] = g;
|
||||
color[2] = b;
|
||||
color[3] = a;
|
||||
set_render_color(r, g, b, a);
|
||||
}
|
||||
GLVolume(float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f);
|
||||
GLVolume(const float *rgba) : GLVolume(rgba[0], rgba[1], rgba[2], rgba[3]) {}
|
||||
|
||||
std::vector<int> load_object(
|
||||
const ModelObject *model_object,
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
const std::string &select_by,
|
||||
const std::string &drag_by);
|
||||
private:
|
||||
// Offset of the volume to be rendered.
|
||||
Pointf3 m_origin;
|
||||
// Rotation around Z axis of the volume to be rendered.
|
||||
float m_angle_z;
|
||||
// Scale factor of the volume to be rendered.
|
||||
float m_scale_factor;
|
||||
// World matrix of the volume to be rendered.
|
||||
std::vector<float> m_world_mat;
|
||||
// Bounding box of this volume, in unscaled coordinates.
|
||||
mutable BoundingBoxf3 m_transformed_bounding_box;
|
||||
// Whether or not is needed to recalculate the world matrix.
|
||||
mutable bool m_dirty;
|
||||
|
||||
int load_wipe_tower_preview(
|
||||
int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs);
|
||||
public:
|
||||
|
||||
// Bounding box of this volume, in unscaled coordinates.
|
||||
BoundingBoxf3 bounding_box;
|
||||
// Offset of the volume to be rendered.
|
||||
Pointf3 origin;
|
||||
// Color of the triangles / quads held by this volume.
|
||||
float color[4];
|
||||
// Color used to render this volume.
|
||||
|
@ -333,10 +316,17 @@ public:
|
|||
// Sets render color in dependence of current state
|
||||
void set_render_color();
|
||||
|
||||
const Pointf3& get_origin() const;
|
||||
void set_origin(const Pointf3& origin);
|
||||
void set_angle_z(float angle_z);
|
||||
void set_scale_factor(float scale_factor);
|
||||
|
||||
int object_idx() const { return this->composite_id / 1000000; }
|
||||
int volume_idx() const { return (this->composite_id / 1000) % 1000; }
|
||||
int instance_idx() const { return this->composite_id % 1000; }
|
||||
BoundingBoxf3 transformed_bounding_box() const { BoundingBoxf3 bb = this->bounding_box; bb.translate(this->origin); return bb; }
|
||||
|
||||
const std::vector<float>& world_matrix() const;
|
||||
BoundingBoxf3 transformed_bounding_box() const;
|
||||
|
||||
bool empty() const { return this->indexed_vertex_array.empty(); }
|
||||
bool indexed() const { return this->indexed_vertex_array.indexed(); }
|
||||
|
@ -344,6 +334,9 @@ public:
|
|||
void set_range(coordf_t low, coordf_t high);
|
||||
void render() const;
|
||||
void render_using_layer_height() const;
|
||||
void render_VBOs(int color_id, int detection_id, int worldmatrix_id) const;
|
||||
void render_legacy() const;
|
||||
|
||||
void finalize_geometry(bool use_VBOs) { this->indexed_vertex_array.finalize_geometry(use_VBOs); }
|
||||
void release_geometry() { this->indexed_vertex_array.release_geometry(); }
|
||||
|
||||
|
|
|
@ -113,6 +113,11 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
|
|||
sizer->Add(all_none_sizer, 0, wxEXPAND);
|
||||
|
||||
SetSizer(sizer);
|
||||
|
||||
if (cboxes.size() > 0) {
|
||||
cboxes[0]->SetValue(true);
|
||||
on_checkbox(cboxes[0], true);
|
||||
}
|
||||
}
|
||||
|
||||
void PrinterPicker::select_all(bool select)
|
||||
|
@ -598,10 +603,10 @@ void ConfigWizardIndex::on_paint(wxPaintEvent & evt)
|
|||
|
||||
static const std::unordered_map<std::string, std::pair<std::string, std::string>> legacy_preset_map {{
|
||||
{ "Original Prusa i3 MK2.ini", std::make_pair("MK2S", "0.4") },
|
||||
{ "Original Prusa i3 MK2 MM Single Mode.ini", std::make_pair("MK2S", "0.4") },
|
||||
{ "Original Prusa i3 MK2 MM Single Mode 0.6 nozzle.ini", std::make_pair("MK2S", "0.6") },
|
||||
{ "Original Prusa i3 MK2 MultiMaterial.ini", std::make_pair("MK2S", "0.4") },
|
||||
{ "Original Prusa i3 MK2 MultiMaterial 0.6 nozzle.ini", std::make_pair("MK2S", "0.6") },
|
||||
{ "Original Prusa i3 MK2 MM Single Mode.ini", std::make_pair("MK2SMM", "0.4") },
|
||||
{ "Original Prusa i3 MK2 MM Single Mode 0.6 nozzle.ini", std::make_pair("MK2SMM", "0.6") },
|
||||
{ "Original Prusa i3 MK2 MultiMaterial.ini", std::make_pair("MK2SMM", "0.4") },
|
||||
{ "Original Prusa i3 MK2 MultiMaterial 0.6 nozzle.ini", std::make_pair("MK2SMM", "0.6") },
|
||||
{ "Original Prusa i3 MK2 0.25 nozzle.ini", std::make_pair("MK2S", "0.25") },
|
||||
{ "Original Prusa i3 MK2 0.6 nozzle.ini", std::make_pair("MK2S", "0.6") },
|
||||
{ "Original Prusa i3 MK3.ini", std::make_pair("MK3", "0.4") },
|
||||
|
@ -809,8 +814,8 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) :
|
|||
topsizer->AddSpacer(INDEX_MARGIN);
|
||||
topsizer->Add(p->hscroll, 1, wxEXPAND);
|
||||
|
||||
p->btn_prev = new wxButton(this, wxID_BACKWARD);
|
||||
p->btn_next = new wxButton(this, wxID_FORWARD);
|
||||
p->btn_prev = new wxButton(this, wxID_NONE, _(L("< &Back")));
|
||||
p->btn_next = new wxButton(this, wxID_NONE, _(L("&Next >")));
|
||||
p->btn_finish = new wxButton(this, wxID_APPLY, _(L("&Finish")));
|
||||
p->btn_cancel = new wxButton(this, wxID_CANCEL);
|
||||
p->btnsizer->AddStretchSpacer();
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
#include <algorithm>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/filepicker.h>
|
||||
|
@ -36,7 +38,7 @@ namespace Slic3r {
|
|||
enum AvrdudeEvent
|
||||
{
|
||||
AE_MESSAGE,
|
||||
AE_PRORGESS,
|
||||
AE_PROGRESS,
|
||||
AE_EXIT,
|
||||
};
|
||||
|
||||
|
@ -62,7 +64,6 @@ struct FirmwareDialog::priv
|
|||
std::vector<Utils::SerialPortInfo> ports;
|
||||
wxFilePickerCtrl *hex_picker;
|
||||
wxStaticText *txt_status;
|
||||
wxStaticText *txt_progress;
|
||||
wxGauge *progressbar;
|
||||
wxCollapsiblePane *spoiler;
|
||||
wxTextCtrl *txt_stdout;
|
||||
|
@ -72,6 +73,8 @@ struct FirmwareDialog::priv
|
|||
wxString btn_flash_label_ready;
|
||||
wxString btn_flash_label_flashing;
|
||||
|
||||
wxTimer timer_pulse;
|
||||
|
||||
// This is a shared pointer holding the background AvrDude task
|
||||
// also serves as a status indication (it is set _iff_ the background task is running, otherwise it is reset).
|
||||
AvrDude::Ptr avrdude;
|
||||
|
@ -83,13 +86,16 @@ struct FirmwareDialog::priv
|
|||
q(q),
|
||||
btn_flash_label_ready(_(L("Flash!"))),
|
||||
btn_flash_label_flashing(_(L("Cancel"))),
|
||||
timer_pulse(q),
|
||||
avrdude_config((fs::path(::Slic3r::resources_dir()) / "avrdude" / "avrdude.conf").string()),
|
||||
progress_tasks_done(0),
|
||||
cancelled(false)
|
||||
{}
|
||||
|
||||
void find_serial_ports();
|
||||
void flashing_status(bool flashing, AvrDudeComplete complete = AC_NONE);
|
||||
void flashing_start(bool flashing_l10n);
|
||||
void flashing_done(AvrDudeComplete complete);
|
||||
size_t hex_lang_offset(const wxString &path);
|
||||
void perform_upload();
|
||||
void cancel();
|
||||
void on_avrdude(const wxCommandEvent &evt);
|
||||
|
@ -116,42 +122,76 @@ void FirmwareDialog::priv::find_serial_ports()
|
|||
}
|
||||
}
|
||||
|
||||
void FirmwareDialog::priv::flashing_status(bool value, AvrDudeComplete complete)
|
||||
void FirmwareDialog::priv::flashing_start(bool flashing_l10n)
|
||||
{
|
||||
if (value) {
|
||||
txt_stdout->Clear();
|
||||
txt_status->SetLabel(_(L("Flashing in progress. Please do not disconnect the printer!")));
|
||||
txt_status->SetForegroundColour(GUI::get_label_clr_modified());
|
||||
port_picker->Disable();
|
||||
btn_rescan->Disable();
|
||||
hex_picker->Disable();
|
||||
btn_close->Disable();
|
||||
btn_flash->SetLabel(btn_flash_label_flashing);
|
||||
progressbar->SetRange(200); // See progress callback below
|
||||
progressbar->SetValue(0);
|
||||
progress_tasks_done = 0;
|
||||
cancelled = false;
|
||||
} else {
|
||||
auto text_color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||
port_picker->Enable();
|
||||
btn_rescan->Enable();
|
||||
hex_picker->Enable();
|
||||
btn_close->Enable();
|
||||
btn_flash->SetLabel(btn_flash_label_ready);
|
||||
txt_status->SetForegroundColour(text_color);
|
||||
progressbar->SetValue(200);
|
||||
txt_stdout->Clear();
|
||||
txt_status->SetLabel(_(L("Flashing in progress. Please do not disconnect the printer!")));
|
||||
txt_status->SetForegroundColour(GUI::get_label_clr_modified());
|
||||
port_picker->Disable();
|
||||
btn_rescan->Disable();
|
||||
hex_picker->Disable();
|
||||
btn_close->Disable();
|
||||
btn_flash->SetLabel(btn_flash_label_flashing);
|
||||
progressbar->SetRange(flashing_l10n ? 500 : 200); // See progress callback below
|
||||
progressbar->SetValue(0);
|
||||
progress_tasks_done = 0;
|
||||
cancelled = false;
|
||||
timer_pulse.Start(50);
|
||||
}
|
||||
|
||||
switch (complete) {
|
||||
case AC_SUCCESS: txt_status->SetLabel(_(L("Flashing succeeded!"))); break;
|
||||
case AC_FAILURE: txt_status->SetLabel(_(L("Flashing failed. Please see the avrdude log below."))); break;
|
||||
case AC_CANCEL: txt_status->SetLabel(_(L("Flashing cancelled."))); break;
|
||||
void FirmwareDialog::priv::flashing_done(AvrDudeComplete complete)
|
||||
{
|
||||
auto text_color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||
port_picker->Enable();
|
||||
btn_rescan->Enable();
|
||||
hex_picker->Enable();
|
||||
btn_close->Enable();
|
||||
btn_flash->SetLabel(btn_flash_label_ready);
|
||||
txt_status->SetForegroundColour(text_color);
|
||||
timer_pulse.Stop();
|
||||
progressbar->SetValue(progressbar->GetRange());
|
||||
|
||||
switch (complete) {
|
||||
case AC_SUCCESS: txt_status->SetLabel(_(L("Flashing succeeded!"))); break;
|
||||
case AC_FAILURE: txt_status->SetLabel(_(L("Flashing failed. Please see the avrdude log below."))); break;
|
||||
case AC_CANCEL: txt_status->SetLabel(_(L("Flashing cancelled."))); break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t FirmwareDialog::priv::hex_lang_offset(const wxString &path)
|
||||
{
|
||||
fs::ifstream file(fs::path(path.wx_str()));
|
||||
if (! file.good()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *hex_terminator = ":00000001FF\r";
|
||||
size_t res = 0;
|
||||
std::string line;
|
||||
while (getline(file, line, '\n').good()) {
|
||||
// Account for LF vs CRLF
|
||||
if (!line.empty() && line.back() != '\r') {
|
||||
line.push_back('\r');
|
||||
}
|
||||
|
||||
if (line == hex_terminator) {
|
||||
if (res == 0) {
|
||||
// This is the first terminator seen, save the position
|
||||
res = file.tellg();
|
||||
} else {
|
||||
// We've found another terminator, return the offset just after the first one
|
||||
// which is the start of the second 'section'.
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FirmwareDialog::priv::perform_upload()
|
||||
{
|
||||
auto filename = hex_picker->GetPath();
|
||||
auto filename = hex_picker->GetPath();
|
||||
std::string port = port_picker->GetValue().ToStdString();
|
||||
int selection = port_picker->GetSelection();
|
||||
if (selection != -1) {
|
||||
|
@ -161,16 +201,32 @@ void FirmwareDialog::priv::perform_upload()
|
|||
}
|
||||
if (filename.IsEmpty() || port.empty()) { return; }
|
||||
|
||||
flashing_status(true);
|
||||
const bool extra_verbose = false; // For debugging
|
||||
const auto lang_offset = hex_lang_offset(filename);
|
||||
const auto filename_utf8 = filename.utf8_str();
|
||||
|
||||
flashing_start(lang_offset > 0);
|
||||
|
||||
// It is ok here to use the q-pointer to the FirmwareDialog
|
||||
// because the dialog ensures it doesn't exit before the background thread is done.
|
||||
auto q = this->q;
|
||||
|
||||
// Init the avrdude object
|
||||
AvrDude avrdude(avrdude_config);
|
||||
|
||||
// Build argument list(s)
|
||||
std::vector<std::string> args {{
|
||||
"-v",
|
||||
extra_verbose ? "-vvvvv" : "-v",
|
||||
"-p", "atmega2560",
|
||||
// Using the "Wiring" mode to program Rambo or Einsy, using the STK500v2 protocol (not the STK500).
|
||||
// The Prusa's avrdude is patched to never send semicolons inside the data packets, as the USB to serial chip
|
||||
// is flashed with a buggy firmware.
|
||||
"-c", "wiring",
|
||||
"-P", port,
|
||||
"-b", "115200", // XXX: is this ok to hardcode?
|
||||
"-b", "115200", // TODO: Allow other rates? Ditto below.
|
||||
"-D",
|
||||
"-U", (boost::format("flash:w:%1%:i") % filename.ToStdString()).str()
|
||||
// XXX: Safe mode?
|
||||
"-U", (boost::format("flash:w:0:%1%:i") % filename_utf8.data()).str(),
|
||||
}};
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Invoking avrdude, arguments: "
|
||||
|
@ -178,26 +234,51 @@ void FirmwareDialog::priv::perform_upload()
|
|||
return a + ' ' + b;
|
||||
});
|
||||
|
||||
// It is ok here to use the q-pointer to the FirmwareDialog
|
||||
// because the dialog ensures it doesn't exit before the background thread is done.
|
||||
auto q = this->q;
|
||||
avrdude.push_args(std::move(args));
|
||||
|
||||
if (lang_offset > 0) {
|
||||
// The hex file also contains another section with l10n data to be flashed into the external flash on MK3 (Einsy)
|
||||
// This is done via another avrdude invocation, here we build arg list for that:
|
||||
std::vector<std::string> args_l10n {{
|
||||
extra_verbose ? "-vvvvv" : "-v",
|
||||
"-p", "atmega2560",
|
||||
// Using the "Arduino" mode to program Einsy's external flash with languages, using the STK500 protocol (not the STK500v2).
|
||||
// The Prusa's avrdude is patched again to never send semicolons inside the data packets.
|
||||
"-c", "arduino",
|
||||
"-P", port,
|
||||
"-b", "115200",
|
||||
"-D",
|
||||
"-u", // disable safe mode
|
||||
"-U", (boost::format("flash:w:%1%:%2%:i") % lang_offset % filename_utf8.data()).str(),
|
||||
}};
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Invoking avrdude for external flash flashing, arguments: "
|
||||
<< std::accumulate(std::next(args_l10n.begin()), args_l10n.end(), args_l10n[0], [](std::string a, const std::string &b) {
|
||||
return a + ' ' + b;
|
||||
});
|
||||
|
||||
avrdude.push_args(std::move(args_l10n));
|
||||
}
|
||||
|
||||
this->avrdude = avrdude
|
||||
.on_message(std::move([q, extra_verbose](const char *msg, unsigned /* size */) {
|
||||
if (extra_verbose) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "avrdude: " << msg;
|
||||
}
|
||||
|
||||
avrdude = AvrDude()
|
||||
.sys_config(avrdude_config)
|
||||
.args(args)
|
||||
.on_message(std::move([q](const char *msg, unsigned /* size */) {
|
||||
auto evt = new wxCommandEvent(EVT_AVRDUDE, q->GetId());
|
||||
auto wxmsg = wxString::FromUTF8(msg);
|
||||
evt->SetExtraLong(AE_MESSAGE);
|
||||
evt->SetString(msg);
|
||||
evt->SetString(std::move(wxmsg));
|
||||
wxQueueEvent(q, evt);
|
||||
}))
|
||||
.on_progress(std::move([q](const char * /* task */, unsigned progress) {
|
||||
auto evt = new wxCommandEvent(EVT_AVRDUDE, q->GetId());
|
||||
evt->SetExtraLong(AE_PRORGESS);
|
||||
evt->SetExtraLong(AE_PROGRESS);
|
||||
evt->SetInt(progress);
|
||||
wxQueueEvent(q, evt);
|
||||
}))
|
||||
.on_complete(std::move([q](int status) {
|
||||
.on_complete(std::move([q](int status, size_t /* args_id */) {
|
||||
auto evt = new wxCommandEvent(EVT_AVRDUDE, q->GetId());
|
||||
evt->SetExtraLong(AE_EXIT);
|
||||
evt->SetInt(status);
|
||||
|
@ -224,19 +305,19 @@ void FirmwareDialog::priv::on_avrdude(const wxCommandEvent &evt)
|
|||
txt_stdout->AppendText(evt.GetString());
|
||||
break;
|
||||
|
||||
case AE_PRORGESS:
|
||||
case AE_PROGRESS:
|
||||
// We try to track overall progress here.
|
||||
// When uploading the firmware, avrdude first reads a littlebit of status data,
|
||||
// then performs write, then reading (verification).
|
||||
// We Pulse() during the first read and combine progress of the latter two tasks.
|
||||
// Avrdude performs 3 tasks per one memory operation ("-U" arg),
|
||||
// first of which is reading of status data (very short).
|
||||
// We use the timer_pulse during the very first task to indicate intialization
|
||||
// and then display overall progress during the latter tasks.
|
||||
|
||||
if (progress_tasks_done == 0) {
|
||||
progressbar->Pulse();
|
||||
} else {
|
||||
if (progress_tasks_done > 0) {
|
||||
progressbar->SetValue(progress_tasks_done - 100 + evt.GetInt());
|
||||
}
|
||||
|
||||
if (evt.GetInt() == 100) {
|
||||
timer_pulse.Stop();
|
||||
progress_tasks_done += 100;
|
||||
}
|
||||
|
||||
|
@ -246,7 +327,7 @@ void FirmwareDialog::priv::on_avrdude(const wxCommandEvent &evt)
|
|||
BOOST_LOG_TRIVIAL(info) << "avrdude exit code: " << evt.GetInt();
|
||||
|
||||
complete_kind = cancelled ? AC_CANCEL : (evt.GetInt() == 0 ? AC_SUCCESS : AC_FAILURE);
|
||||
flashing_status(false, complete_kind);
|
||||
flashing_done(complete_kind);
|
||||
|
||||
// Make sure the background thread is collected and the AvrDude object reset
|
||||
if (avrdude) { avrdude->join(); }
|
||||
|
@ -374,6 +455,8 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
|
|||
}
|
||||
});
|
||||
|
||||
Bind(wxEVT_TIMER, [this](wxTimerEvent &evt) { this->p->progressbar->Pulse(); });
|
||||
|
||||
Bind(EVT_AVRDUDE, [this](wxCommandEvent &evt) { this->p->on_avrdude(evt); });
|
||||
|
||||
Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent &evt) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "GLCanvas3D.hpp"
|
||||
|
||||
#include "../../libslic3r/libslic3r.h"
|
||||
#include "../../slic3r/GUI/3DScene.hpp"
|
||||
#include "../../slic3r/GUI/GLShader.hpp"
|
||||
#include "../../slic3r/GUI/GUI.hpp"
|
||||
|
@ -41,6 +42,11 @@ static const float VIEW_REAR[2] = { 180.0f, 90.0f };
|
|||
static const float VARIABLE_LAYER_THICKNESS_BAR_WIDTH = 70.0f;
|
||||
static const float VARIABLE_LAYER_THICKNESS_RESET_BUTTON_HEIGHT = 22.0f;
|
||||
|
||||
static const float UNIT_MATRIX[] = { 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
@ -719,6 +725,12 @@ void GLCanvas3D::Shader::set_uniform(const std::string& name, float value) const
|
|||
m_shader->set_uniform(name.c_str(), value);
|
||||
}
|
||||
|
||||
void GLCanvas3D::Shader::set_uniform(const std::string& name, const float* matrix) const
|
||||
{
|
||||
if (m_shader != nullptr)
|
||||
m_shader->set_uniform(name.c_str(), matrix);
|
||||
}
|
||||
|
||||
const GLShader* GLCanvas3D::Shader::get_shader() const
|
||||
{
|
||||
return m_shader;
|
||||
|
@ -952,6 +964,8 @@ void GLCanvas3D::LayersEditing::_render_active_object_annotations(const GLCanvas
|
|||
m_shader.set_uniform("z_texture_row_to_normalized", 1.0f / (float)volume.layer_height_texture_height());
|
||||
m_shader.set_uniform("z_cursor", max_z * get_cursor_z_relative(canvas));
|
||||
m_shader.set_uniform("z_cursor_band_width", band_width);
|
||||
// The shader requires the original model coordinates when rendering to the texture, so we pass it the unit matrix
|
||||
m_shader.set_uniform("volume_world_matrix", UNIT_MATRIX);
|
||||
|
||||
GLsizei w = (GLsizei)volume.layer_height_texture_width();
|
||||
GLsizei h = (GLsizei)volume.layer_height_texture_height();
|
||||
|
@ -1042,7 +1056,9 @@ const Pointf3 GLCanvas3D::Mouse::Drag::Invalid_3D_Point(DBL_MAX, DBL_MAX, DBL_MA
|
|||
GLCanvas3D::Mouse::Drag::Drag()
|
||||
: start_position_2D(Invalid_2D_Point)
|
||||
, start_position_3D(Invalid_3D_Point)
|
||||
, volume_idx(-1)
|
||||
, move_with_ctrl(false)
|
||||
, move_volume_idx(-1)
|
||||
, gizmo_volume_idx(-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -2765,6 +2781,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
{
|
||||
update_gizmos_data();
|
||||
m_gizmos.start_dragging();
|
||||
m_mouse.drag.gizmo_volume_idx = _get_first_selected_volume_id();
|
||||
m_dirty = true;
|
||||
}
|
||||
else
|
||||
|
@ -2812,7 +2829,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
if (volume_bbox.contains(pos3d))
|
||||
{
|
||||
// The dragging operation is initiated.
|
||||
m_mouse.drag.volume_idx = volume_idx;
|
||||
m_mouse.drag.move_with_ctrl = evt.ControlDown();
|
||||
m_mouse.drag.move_volume_idx = volume_idx;
|
||||
m_mouse.drag.start_position_3D = pos3d;
|
||||
// Remember the shift to to the object center.The object center will later be used
|
||||
// to limit the object placement close to the bed.
|
||||
|
@ -2828,7 +2846,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (evt.Dragging() && evt.LeftIsDown() && !gizmos_overlay_contains_mouse && (m_layers_editing.state == LayersEditing::Unknown) && (m_mouse.drag.volume_idx != -1))
|
||||
else if (evt.Dragging() && evt.LeftIsDown() && !gizmos_overlay_contains_mouse && (m_layers_editing.state == LayersEditing::Unknown) && (m_mouse.drag.move_volume_idx != -1))
|
||||
{
|
||||
m_mouse.dragging = true;
|
||||
|
||||
|
@ -2851,24 +2869,30 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
// Calculate the translation vector.
|
||||
Vectorf3 vector = m_mouse.drag.start_position_3D.vector_to(cur_pos);
|
||||
// Get the volume being dragged.
|
||||
GLVolume* volume = m_volumes.volumes[m_mouse.drag.volume_idx];
|
||||
GLVolume* volume = m_volumes.volumes[m_mouse.drag.move_volume_idx];
|
||||
// Get all volumes belonging to the same group, if any.
|
||||
std::vector<GLVolume*> volumes;
|
||||
if (volume->drag_group_id == -1)
|
||||
int group_id = m_mouse.drag.move_with_ctrl ? volume->select_group_id : volume->drag_group_id;
|
||||
if (group_id == -1)
|
||||
volumes.push_back(volume);
|
||||
else
|
||||
{
|
||||
for (GLVolume* v : m_volumes.volumes)
|
||||
{
|
||||
if ((v != nullptr) && (v->drag_group_id == volume->drag_group_id))
|
||||
volumes.push_back(v);
|
||||
if (v != nullptr)
|
||||
{
|
||||
if ((m_mouse.drag.move_with_ctrl && (v->select_group_id == group_id)) || (v->drag_group_id == group_id))
|
||||
volumes.push_back(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply new temporary volume origin and ignore Z.
|
||||
for (GLVolume* v : volumes)
|
||||
{
|
||||
v->origin.translate(vector.x, vector.y, 0.0);
|
||||
Pointf3 origin = v->get_origin();
|
||||
origin.translate(vector.x, vector.y, 0.0);
|
||||
v->set_origin(origin);
|
||||
}
|
||||
|
||||
m_mouse.drag.start_position_3D = cur_pos;
|
||||
|
@ -2882,16 +2906,43 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
const Pointf3& cur_pos = _mouse_to_bed_3d(pos);
|
||||
m_gizmos.update(Pointf(cur_pos.x, cur_pos.y));
|
||||
|
||||
std::vector<GLVolume*> volumes;
|
||||
if (m_mouse.drag.gizmo_volume_idx != -1)
|
||||
{
|
||||
GLVolume* volume = m_volumes.volumes[m_mouse.drag.gizmo_volume_idx];
|
||||
// Get all volumes belonging to the same group, if any.
|
||||
if (volume->select_group_id == -1)
|
||||
volumes.push_back(volume);
|
||||
else
|
||||
{
|
||||
for (GLVolume* v : m_volumes.volumes)
|
||||
{
|
||||
if ((v != nullptr) && (v->select_group_id == volume->select_group_id))
|
||||
volumes.push_back(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (m_gizmos.get_current_type())
|
||||
{
|
||||
case Gizmos::Scale:
|
||||
{
|
||||
m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale());
|
||||
// Apply new temporary scale factor
|
||||
float scale_factor = m_gizmos.get_scale();
|
||||
for (GLVolume* v : volumes)
|
||||
{
|
||||
v->set_scale_factor(scale_factor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Gizmos::Rotate:
|
||||
{
|
||||
m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z());
|
||||
// Apply new temporary angle_z
|
||||
float angle_z = m_gizmos.get_angle_z();
|
||||
for (GLVolume* v : volumes)
|
||||
{
|
||||
v->set_angle_z(angle_z);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -2954,19 +3005,19 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
if (layer_editing_object_idx != -1)
|
||||
m_on_model_update_callback.call();
|
||||
}
|
||||
else if ((m_mouse.drag.volume_idx != -1) && m_mouse.dragging)
|
||||
else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging)
|
||||
{
|
||||
// get all volumes belonging to the same group, if any
|
||||
std::vector<int> volume_idxs;
|
||||
int vol_id = m_mouse.drag.volume_idx;
|
||||
int group_id = m_volumes.volumes[vol_id]->drag_group_id;
|
||||
int vol_id = m_mouse.drag.move_volume_idx;
|
||||
int group_id = m_mouse.drag.move_with_ctrl ? m_volumes.volumes[vol_id]->select_group_id : m_volumes.volumes[vol_id]->drag_group_id;
|
||||
if (group_id == -1)
|
||||
volume_idxs.push_back(vol_id);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < (int)m_volumes.volumes.size(); ++i)
|
||||
{
|
||||
if (m_volumes.volumes[i]->drag_group_id == group_id)
|
||||
if ((m_mouse.drag.move_with_ctrl && (m_volumes.volumes[i]->select_group_id == group_id)) || (m_volumes.volumes[i]->drag_group_id == group_id))
|
||||
volume_idxs.push_back(i);
|
||||
}
|
||||
}
|
||||
|
@ -2984,10 +3035,26 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
}
|
||||
else if (evt.LeftUp() && m_gizmos.is_dragging())
|
||||
{
|
||||
switch (m_gizmos.get_current_type())
|
||||
{
|
||||
case Gizmos::Scale:
|
||||
{
|
||||
m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale());
|
||||
break;
|
||||
}
|
||||
case Gizmos::Rotate:
|
||||
{
|
||||
m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_gizmos.stop_dragging();
|
||||
}
|
||||
|
||||
m_mouse.drag.volume_idx = -1;
|
||||
m_mouse.drag.move_volume_idx = -1;
|
||||
m_mouse.drag.gizmo_volume_idx = -1;
|
||||
m_mouse.set_start_position_3D_as_invalid();
|
||||
m_mouse.set_start_position_2D_as_invalid();
|
||||
m_mouse.dragging = false;
|
||||
|
@ -3706,6 +3773,35 @@ int GLCanvas3D::_get_first_selected_object_id() const
|
|||
return -1;
|
||||
}
|
||||
|
||||
int GLCanvas3D::_get_first_selected_volume_id() const
|
||||
{
|
||||
if (m_print != nullptr)
|
||||
{
|
||||
int objects_count = (int)m_print->objects.size();
|
||||
|
||||
for (const GLVolume* vol : m_volumes.volumes)
|
||||
{
|
||||
if ((vol != nullptr) && vol->selected)
|
||||
{
|
||||
int object_id = vol->select_group_id / 1000000;
|
||||
// Objects with object_id >= 1000 have a specific meaning, for example the wipe tower proxy.
|
||||
if (object_id < 10000)
|
||||
{
|
||||
int volume_id = 0;
|
||||
for (int i = 0; i < object_id; ++i)
|
||||
{
|
||||
const PrintObject* obj = m_print->objects[i];
|
||||
const ModelObject* model = obj->model_object();
|
||||
volume_id += model->instances.size();
|
||||
}
|
||||
return volume_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int hex_digit_to_int(const char c)
|
||||
{
|
||||
return
|
||||
|
@ -4311,13 +4407,14 @@ void GLCanvas3D::_on_move(const std::vector<int>& volume_idxs)
|
|||
{
|
||||
// Move a regular object.
|
||||
ModelObject* model_object = m_model->objects[obj_idx];
|
||||
model_object->instances[instance_idx]->offset.translate(volume->origin.x, volume->origin.y);
|
||||
const Pointf3& origin = volume->get_origin();
|
||||
model_object->instances[instance_idx]->offset = Pointf(origin.x, origin.y);
|
||||
model_object->invalidate_bounding_box();
|
||||
object_moved = true;
|
||||
}
|
||||
else if (obj_idx == 1000)
|
||||
// Move a wipe tower proxy.
|
||||
wipe_tower_origin = volume->origin;
|
||||
wipe_tower_origin = volume->get_origin();
|
||||
}
|
||||
|
||||
if (object_moved)
|
||||
|
|
|
@ -225,6 +225,7 @@ public:
|
|||
void stop_using() const;
|
||||
|
||||
void set_uniform(const std::string& name, float value) const;
|
||||
void set_uniform(const std::string& name, const float* matrix) const;
|
||||
|
||||
const GLShader* get_shader() const;
|
||||
|
||||
|
@ -302,7 +303,10 @@ public:
|
|||
Point start_position_2D;
|
||||
Pointf3 start_position_3D;
|
||||
Vectorf3 volume_center_offset;
|
||||
int volume_idx;
|
||||
|
||||
bool move_with_ctrl;
|
||||
int move_volume_idx;
|
||||
int gizmo_volume_idx;
|
||||
|
||||
public:
|
||||
Drag();
|
||||
|
@ -617,6 +621,7 @@ private:
|
|||
void _stop_timer();
|
||||
|
||||
int _get_first_selected_object_id() const;
|
||||
int _get_first_selected_volume_id() const;
|
||||
|
||||
// generates gcode extrusion paths geometry
|
||||
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||
|
|
|
@ -214,6 +214,17 @@ bool GLShader::set_uniform(const char *name, float value) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool GLShader::set_uniform(const char* name, const float* matrix) const
|
||||
{
|
||||
int id = get_uniform_location(name);
|
||||
if (id >= 0)
|
||||
{
|
||||
::glUniformMatrix4fv(id, 1, GL_FALSE, (const GLfloat*)matrix);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
# Set shader vector
|
||||
sub SetVector
|
||||
|
|
|
@ -25,6 +25,7 @@ public:
|
|||
int get_uniform_location(const char *name) const;
|
||||
|
||||
bool set_uniform(const char *name, float value) const;
|
||||
bool set_uniform(const char* name, const float* matrix) const;
|
||||
|
||||
void enable() const;
|
||||
void disable() const;
|
||||
|
|
|
@ -423,7 +423,7 @@ bool check_unsaved_changes()
|
|||
|
||||
bool config_wizard_startup(bool app_config_exists)
|
||||
{
|
||||
if (! app_config_exists || g_PresetBundle->has_defauls_only()) {
|
||||
if (! app_config_exists || g_PresetBundle->printers.size() <= 1) {
|
||||
config_wizard(ConfigWizard::RR_DATA_EMPTY);
|
||||
return true;
|
||||
} else if (g_AppConfig->legacy_datadir()) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue