mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 08:47:52 -06:00
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_custom_bed
This commit is contained in:
commit
9cb1a584e1
17 changed files with 621 additions and 474 deletions
|
@ -169,6 +169,9 @@ static inline Point wipe_tower_point_to_object_point(GCode &gcodegen, const Vec2
|
||||||
|
|
||||||
std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const
|
std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const
|
||||||
{
|
{
|
||||||
|
if (new_extruder_id != -1 && new_extruder_id != tcr.new_tool)
|
||||||
|
throw std::invalid_argument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect.");
|
||||||
|
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
|
|
||||||
// Toolchangeresult.gcode assumes the wipe tower corner is at the origin
|
// Toolchangeresult.gcode assumes the wipe tower corner is at the origin
|
||||||
|
@ -182,8 +185,11 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
||||||
end_pos = Eigen::Rotation2Df(alpha) * end_pos;
|
end_pos = Eigen::Rotation2Df(alpha) * end_pos;
|
||||||
end_pos += m_wipe_tower_pos;
|
end_pos += m_wipe_tower_pos;
|
||||||
}
|
}
|
||||||
std::string tcr_rotated_gcode = tcr.priming ? tcr.gcode : rotate_wipe_tower_moves(tcr.gcode, tcr.start_pos, m_wipe_tower_pos, alpha);
|
|
||||||
|
Vec2f wipe_tower_offset = tcr.priming ? Vec2f::Zero() : m_wipe_tower_pos;
|
||||||
|
float wipe_tower_rotation = tcr.priming ? 0.f : alpha;
|
||||||
|
|
||||||
|
std::string tcr_rotated_gcode = post_process_wipe_tower_moves(tcr, wipe_tower_offset, wipe_tower_rotation);
|
||||||
|
|
||||||
// Disable linear advance for the wipe tower operations.
|
// Disable linear advance for the wipe tower operations.
|
||||||
gcode += (gcodegen.config().gcode_flavor == gcfRepRap ? std::string("M572 D0 S0\n") : std::string("M900 K0\n"));
|
gcode += (gcodegen.config().gcode_flavor == gcfRepRap ? std::string("M572 D0 S0\n") : std::string("M900 K0\n"));
|
||||||
|
@ -285,17 +291,21 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
||||||
|
|
||||||
// This function postprocesses gcode_original, rotates and moves all G1 extrusions and returns resulting gcode
|
// This function postprocesses gcode_original, rotates and moves all G1 extrusions and returns resulting gcode
|
||||||
// Starting position has to be supplied explicitely (otherwise it would fail in case first G1 command only contained one coordinate)
|
// Starting position has to be supplied explicitely (otherwise it would fail in case first G1 command only contained one coordinate)
|
||||||
std::string WipeTowerIntegration::rotate_wipe_tower_moves(const std::string& gcode_original, const Vec2f& start_pos, const Vec2f& translation, float angle) const
|
std::string WipeTowerIntegration::post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& translation, float angle) const
|
||||||
{
|
{
|
||||||
std::istringstream gcode_str(gcode_original);
|
Vec2f extruder_offset = m_extruder_offsets[tcr.initial_tool].cast<float>();
|
||||||
|
|
||||||
|
std::istringstream gcode_str(tcr.gcode);
|
||||||
std::string gcode_out;
|
std::string gcode_out;
|
||||||
std::string line;
|
std::string line;
|
||||||
Vec2f pos = start_pos;
|
Vec2f pos = tcr.start_pos;
|
||||||
Vec2f transformed_pos;
|
Vec2f transformed_pos = pos;
|
||||||
Vec2f old_pos(-1000.1f, -1000.1f);
|
Vec2f old_pos(-1000.1f, -1000.1f);
|
||||||
|
|
||||||
while (gcode_str) {
|
while (gcode_str) {
|
||||||
std::getline(gcode_str, line); // we read the gcode line by line
|
std::getline(gcode_str, line); // we read the gcode line by line
|
||||||
|
|
||||||
|
// All G1 commands should be translated and rotated
|
||||||
if (line.find("G1 ") == 0) {
|
if (line.find("G1 ") == 0) {
|
||||||
std::ostringstream line_out;
|
std::ostringstream line_out;
|
||||||
std::istringstream line_str(line);
|
std::istringstream line_str(line);
|
||||||
|
@ -317,17 +327,34 @@ std::string WipeTowerIntegration::rotate_wipe_tower_moves(const std::string& gco
|
||||||
|
|
||||||
if (transformed_pos != old_pos) {
|
if (transformed_pos != old_pos) {
|
||||||
line = line_out.str();
|
line = line_out.str();
|
||||||
char buf[2048] = "G1";
|
std::ostringstream oss;
|
||||||
|
oss << std::fixed << std::setprecision(3) << "G1 ";
|
||||||
if (transformed_pos.x() != old_pos.x())
|
if (transformed_pos.x() != old_pos.x())
|
||||||
sprintf(buf + strlen(buf), " X%.3f", transformed_pos.x());
|
oss << " X" << transformed_pos.x() - extruder_offset.x();
|
||||||
if (transformed_pos.y() != old_pos.y())
|
if (transformed_pos.y() != old_pos.y())
|
||||||
sprintf(buf + strlen(buf), " Y%.3f", transformed_pos.y());
|
oss << " Y" << transformed_pos.y() - extruder_offset.y();
|
||||||
|
|
||||||
line.replace(line.find("G1 "), 3, buf);
|
line.replace(line.find("G1 "), 3, oss.str());
|
||||||
old_pos = transformed_pos;
|
old_pos = transformed_pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gcode_out += line + "\n";
|
gcode_out += line + "\n";
|
||||||
|
|
||||||
|
// If this was a toolchange command, we should change current extruder offset
|
||||||
|
if (line == "[toolchange_gcode]") {
|
||||||
|
extruder_offset = m_extruder_offsets[tcr.new_tool].cast<float>();
|
||||||
|
|
||||||
|
// If the extruder offset changed, add an extra move so everything is continuous
|
||||||
|
if (extruder_offset != m_extruder_offsets[tcr.initial_tool].cast<float>()) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << std::fixed << std::setprecision(3)
|
||||||
|
<< "G1 X" << transformed_pos.x() - extruder_offset.x()
|
||||||
|
<< " Y" << transformed_pos.y() - extruder_offset.y()
|
||||||
|
<< "\n";
|
||||||
|
gcode_out += oss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return gcode_out;
|
return gcode_out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ public:
|
||||||
m_right(float(/*print_config.wipe_tower_x.value +*/ print_config.wipe_tower_width.value)),
|
m_right(float(/*print_config.wipe_tower_x.value +*/ print_config.wipe_tower_width.value)),
|
||||||
m_wipe_tower_pos(float(print_config.wipe_tower_x.value), float(print_config.wipe_tower_y.value)),
|
m_wipe_tower_pos(float(print_config.wipe_tower_x.value), float(print_config.wipe_tower_y.value)),
|
||||||
m_wipe_tower_rotation(float(print_config.wipe_tower_rotation_angle)),
|
m_wipe_tower_rotation(float(print_config.wipe_tower_rotation_angle)),
|
||||||
|
m_extruder_offsets(print_config.extruder_offset.values),
|
||||||
m_priming(priming),
|
m_priming(priming),
|
||||||
m_tool_changes(tool_changes),
|
m_tool_changes(tool_changes),
|
||||||
m_final_purge(final_purge),
|
m_final_purge(final_purge),
|
||||||
|
@ -107,14 +108,16 @@ private:
|
||||||
WipeTowerIntegration& operator=(const WipeTowerIntegration&);
|
WipeTowerIntegration& operator=(const WipeTowerIntegration&);
|
||||||
std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const;
|
std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const;
|
||||||
|
|
||||||
// Postprocesses gcode: rotates and moves all G1 extrusions and returns result
|
// Postprocesses gcode: rotates and moves G1 extrusions and returns result
|
||||||
std::string rotate_wipe_tower_moves(const std::string& gcode_original, const Vec2f& start_pos, const Vec2f& translation, float angle) const;
|
std::string post_process_wipe_tower_moves(const WipeTower::ToolChangeResult& tcr, const Vec2f& translation, float angle) const;
|
||||||
|
|
||||||
// Left / right edges of the wipe tower, for the planning of wipe moves.
|
// Left / right edges of the wipe tower, for the planning of wipe moves.
|
||||||
const float m_left;
|
const float m_left;
|
||||||
const float m_right;
|
const float m_right;
|
||||||
const Vec2f m_wipe_tower_pos;
|
const Vec2f m_wipe_tower_pos;
|
||||||
const float m_wipe_tower_rotation;
|
const float m_wipe_tower_rotation;
|
||||||
|
const std::vector<Vec2d> m_extruder_offsets;
|
||||||
|
|
||||||
// Reference to cached values at the Printer class.
|
// Reference to cached values at the Printer class.
|
||||||
const std::vector<WipeTower::ToolChangeResult> &m_priming;
|
const std::vector<WipeTower::ToolChangeResult> &m_priming;
|
||||||
const std::vector<std::vector<WipeTower::ToolChangeResult>> &m_tool_changes;
|
const std::vector<std::vector<WipeTower::ToolChangeResult>> &m_tool_changes;
|
||||||
|
|
|
@ -553,7 +553,7 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
|
||||||
result.elapsed_time = writer.elapsed_time();
|
result.elapsed_time = writer.elapsed_time();
|
||||||
result.extrusions = writer.extrusions();
|
result.extrusions = writer.extrusions();
|
||||||
result.start_pos = writer.start_pos_rotated();
|
result.start_pos = writer.start_pos_rotated();
|
||||||
result.end_pos = writer.pos_rotated();
|
result.end_pos = writer.pos();
|
||||||
|
|
||||||
results.push_back(std::move(result));
|
results.push_back(std::move(result));
|
||||||
|
|
||||||
|
@ -643,7 +643,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_
|
||||||
m_is_first_layer ? m_filpar[tool].first_layer_temperature : m_filpar[tool].temperature);
|
m_is_first_layer ? m_filpar[tool].first_layer_temperature : m_filpar[tool].temperature);
|
||||||
toolchange_Change(writer, tool, m_filpar[tool].material); // Change the tool, set a speed override for soluble and flex materials.
|
toolchange_Change(writer, tool, m_filpar[tool].material); // Change the tool, set a speed override for soluble and flex materials.
|
||||||
toolchange_Load(writer, cleaning_box);
|
toolchange_Load(writer, cleaning_box);
|
||||||
writer.travel(writer.x(),writer.y()-m_perimeter_width); // cooling and loading were done a bit down the road
|
writer.travel(writer.x(), writer.y()-m_perimeter_width); // cooling and loading were done a bit down the road
|
||||||
toolchange_Wipe(writer, cleaning_box, wipe_volume); // Wipe the newly loaded filament until the end of the assigned wipe area.
|
toolchange_Wipe(writer, cleaning_box, wipe_volume); // Wipe the newly loaded filament until the end of the assigned wipe area.
|
||||||
++ m_num_tool_changes;
|
++ m_num_tool_changes;
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -139,13 +139,15 @@ public:
|
||||||
|
|
||||||
m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter
|
m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter
|
||||||
|
|
||||||
std::stringstream stream{m_semm ? ramming_parameters : std::string()};
|
if (m_semm) {
|
||||||
float speed = 0.f;
|
std::stringstream stream{ramming_parameters};
|
||||||
stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator;
|
float speed = 0.f;
|
||||||
m_filpar[idx].ramming_line_width_multiplicator /= 100;
|
stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator;
|
||||||
m_filpar[idx].ramming_step_multiplicator /= 100;
|
m_filpar[idx].ramming_line_width_multiplicator /= 100;
|
||||||
while (stream >> speed)
|
m_filpar[idx].ramming_step_multiplicator /= 100;
|
||||||
m_filpar[idx].ramming_speed.push_back(speed);
|
while (stream >> speed)
|
||||||
|
m_filpar[idx].ramming_speed.push_back(speed);
|
||||||
|
}
|
||||||
|
|
||||||
m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later
|
m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later
|
||||||
}
|
}
|
||||||
|
@ -241,8 +243,8 @@ public:
|
||||||
int cooling_moves = 0;
|
int cooling_moves = 0;
|
||||||
float cooling_initial_speed = 0.f;
|
float cooling_initial_speed = 0.f;
|
||||||
float cooling_final_speed = 0.f;
|
float cooling_final_speed = 0.f;
|
||||||
float ramming_line_width_multiplicator = 0.f;
|
float ramming_line_width_multiplicator = 1.f;
|
||||||
float ramming_step_multiplicator = 0.f;
|
float ramming_step_multiplicator = 1.f;
|
||||||
float max_e_speed = std::numeric_limits<float>::max();
|
float max_e_speed = std::numeric_limits<float>::max();
|
||||||
std::vector<float> ramming_speed;
|
std::vector<float> ramming_speed;
|
||||||
float nozzle_diameter;
|
float nozzle_diameter;
|
||||||
|
|
|
@ -1971,4 +1971,4 @@ CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelObject)
|
||||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelVolume)
|
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelVolume)
|
||||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelInstance)
|
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::ModelInstance)
|
||||||
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::Model)
|
CEREAL_REGISTER_POLYMORPHIC_RELATION(Slic3r::ObjectBase, Slic3r::Model)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,8 @@ namespace cereal {
|
||||||
class BinaryOutputArchive;
|
class BinaryOutputArchive;
|
||||||
template <class T> void load_optional(BinaryInputArchive &ar, std::shared_ptr<const T> &ptr);
|
template <class T> void load_optional(BinaryInputArchive &ar, std::shared_ptr<const T> &ptr);
|
||||||
template <class T> void save_optional(BinaryOutputArchive &ar, const std::shared_ptr<const T> &ptr);
|
template <class T> void save_optional(BinaryOutputArchive &ar, const std::shared_ptr<const T> &ptr);
|
||||||
|
template <class T> void load_by_value(BinaryInputArchive &ar, T &obj);
|
||||||
|
template <class T> void save_by_value(BinaryOutputArchive &ar, const T &obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -31,6 +33,7 @@ class ModelInstance;
|
||||||
class ModelMaterial;
|
class ModelMaterial;
|
||||||
class ModelObject;
|
class ModelObject;
|
||||||
class ModelVolume;
|
class ModelVolume;
|
||||||
|
class ModelWipeTower;
|
||||||
class Print;
|
class Print;
|
||||||
class SLAPrint;
|
class SLAPrint;
|
||||||
|
|
||||||
|
@ -66,6 +69,21 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
|
template<typename T>
|
||||||
|
class StaticSerializationWrapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StaticSerializationWrapper(T &wrap) : wrapped(wrap) {}
|
||||||
|
private:
|
||||||
|
friend class cereal::access;
|
||||||
|
friend class UndoRedo::StackImpl;
|
||||||
|
template<class Archive> void load(Archive &ar) { cereal::load_by_value(ar, wrapped); }
|
||||||
|
template<class Archive> void save(Archive &ar) const { cereal::save_by_value(ar, wrapped); }
|
||||||
|
T& wrapped;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
typedef std::string t_model_material_id;
|
typedef std::string t_model_material_id;
|
||||||
typedef std::string t_model_material_attribute;
|
typedef std::string t_model_material_attribute;
|
||||||
typedef std::map<t_model_material_attribute, std::string> t_model_material_attributes;
|
typedef std::map<t_model_material_attribute, std::string> t_model_material_attributes;
|
||||||
|
@ -140,7 +158,8 @@ private:
|
||||||
ModelMaterial() : ObjectBase(-1), config(-1), m_model(nullptr) { assert(this->id().invalid()); assert(this->config.id().invalid()); }
|
ModelMaterial() : ObjectBase(-1), config(-1), m_model(nullptr) { assert(this->id().invalid()); assert(this->config.id().invalid()); }
|
||||||
template<class Archive> void serialize(Archive &ar) {
|
template<class Archive> void serialize(Archive &ar) {
|
||||||
assert(this->id().invalid()); assert(this->config.id().invalid());
|
assert(this->id().invalid()); assert(this->config.id().invalid());
|
||||||
ar(attributes, config);
|
Internal::StaticSerializationWrapper<ModelConfig> config_wrapper(config);
|
||||||
|
ar(attributes, config_wrapper);
|
||||||
// assert(this->id().valid()); assert(this->config.id().valid());
|
// assert(this->id().valid()); assert(this->config.id().valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +368,8 @@ private:
|
||||||
}
|
}
|
||||||
template<class Archive> void serialize(Archive &ar) {
|
template<class Archive> void serialize(Archive &ar) {
|
||||||
ar(cereal::base_class<ObjectBase>(this));
|
ar(cereal::base_class<ObjectBase>(this));
|
||||||
ar(name, input_file, instances, volumes, config, layer_config_ranges, layer_height_profile, sla_support_points, sla_points_status, origin_translation,
|
Internal::StaticSerializationWrapper<ModelConfig> config_wrapper(config);
|
||||||
|
ar(name, input_file, instances, volumes, config_wrapper, layer_config_ranges, layer_height_profile, sla_support_points, sla_points_status, origin_translation,
|
||||||
m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid);
|
m_bounding_box, m_bounding_box_valid, m_raw_bounding_box, m_raw_bounding_box_valid, m_raw_mesh_bounding_box, m_raw_mesh_bounding_box_valid);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -535,7 +555,8 @@ private:
|
||||||
}
|
}
|
||||||
template<class Archive> void load(Archive &ar) {
|
template<class Archive> void load(Archive &ar) {
|
||||||
bool has_convex_hull;
|
bool has_convex_hull;
|
||||||
ar(name, config, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
ar(name, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
||||||
|
cereal::load_by_value(ar, config);
|
||||||
assert(m_mesh);
|
assert(m_mesh);
|
||||||
if (has_convex_hull) {
|
if (has_convex_hull) {
|
||||||
cereal::load_optional(ar, m_convex_hull);
|
cereal::load_optional(ar, m_convex_hull);
|
||||||
|
@ -547,7 +568,8 @@ private:
|
||||||
}
|
}
|
||||||
template<class Archive> void save(Archive &ar) const {
|
template<class Archive> void save(Archive &ar) const {
|
||||||
bool has_convex_hull = m_convex_hull.get() != nullptr;
|
bool has_convex_hull = m_convex_hull.get() != nullptr;
|
||||||
ar(name, config, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
ar(name, m_mesh, m_type, m_material_id, m_transformation, m_is_splittable, has_convex_hull);
|
||||||
|
cereal::save_by_value(ar, config);
|
||||||
if (has_convex_hull)
|
if (has_convex_hull)
|
||||||
cereal::save_optional(ar, m_convex_hull);
|
cereal::save_optional(ar, m_convex_hull);
|
||||||
}
|
}
|
||||||
|
@ -650,6 +672,35 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ModelWipeTower final : public ObjectBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vec2d position;
|
||||||
|
double rotation;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class cereal::access;
|
||||||
|
friend class UndoRedo::StackImpl;
|
||||||
|
friend class Model;
|
||||||
|
|
||||||
|
// Constructors to be only called by derived classes.
|
||||||
|
// Default constructor to assign a unique ID.
|
||||||
|
explicit ModelWipeTower() {}
|
||||||
|
// Constructor with ignored int parameter to assign an invalid ID, to be replaced
|
||||||
|
// by an existing ID copied from elsewhere.
|
||||||
|
explicit ModelWipeTower(int) : ObjectBase(-1) {}
|
||||||
|
// Copy constructor copies the ID.
|
||||||
|
explicit ModelWipeTower(const ModelWipeTower &cfg) = default;
|
||||||
|
|
||||||
|
// Disabled methods.
|
||||||
|
ModelWipeTower(ModelWipeTower &&rhs) = delete;
|
||||||
|
ModelWipeTower& operator=(const ModelWipeTower &rhs) = delete;
|
||||||
|
ModelWipeTower& operator=(ModelWipeTower &&rhs) = delete;
|
||||||
|
|
||||||
|
// For serialization / deserialization of ModelWipeTower composed into another class into the Undo / Redo stack as a separate object.
|
||||||
|
template<typename Archive> void serialize(Archive &ar) { ar(position, rotation); }
|
||||||
|
};
|
||||||
|
|
||||||
// The print bed content.
|
// The print bed content.
|
||||||
// Description of a triangular model with multiple materials, multiple instances with various affine transformations
|
// Description of a triangular model with multiple materials, multiple instances with various affine transformations
|
||||||
// and with multiple modifier meshes.
|
// and with multiple modifier meshes.
|
||||||
|
@ -665,6 +716,8 @@ public:
|
||||||
ModelMaterialMap materials;
|
ModelMaterialMap materials;
|
||||||
// Objects are owned by a model. Each model may have multiple instances, each instance having its own transformation (shift, scale, rotation).
|
// Objects are owned by a model. Each model may have multiple instances, each instance having its own transformation (shift, scale, rotation).
|
||||||
ModelObjectPtrs objects;
|
ModelObjectPtrs objects;
|
||||||
|
// Wipe tower object.
|
||||||
|
ModelWipeTower wipe_tower;
|
||||||
|
|
||||||
// Default constructor assigns a new ID to the model.
|
// Default constructor assigns a new ID to the model.
|
||||||
Model() { assert(this->id().valid()); }
|
Model() { assert(this->id().valid()); }
|
||||||
|
@ -742,7 +795,8 @@ private:
|
||||||
friend class cereal::access;
|
friend class cereal::access;
|
||||||
friend class UndoRedo::StackImpl;
|
friend class UndoRedo::StackImpl;
|
||||||
template<class Archive> void serialize(Archive &ar) {
|
template<class Archive> void serialize(Archive &ar) {
|
||||||
ar(materials, objects);
|
Internal::StaticSerializationWrapper<ModelWipeTower> wipe_tower_wrapper(wipe_tower);
|
||||||
|
ar(materials, objects, wipe_tower_wrapper);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -778,6 +832,7 @@ void check_model_ids_equal(const Model &model1, const Model &model2);
|
||||||
namespace cereal
|
namespace cereal
|
||||||
{
|
{
|
||||||
template <class Archive> struct specialize<Archive, Slic3r::ModelVolume, cereal::specialization::member_load_save> {};
|
template <class Archive> struct specialize<Archive, Slic3r::ModelVolume, cereal::specialization::member_load_save> {};
|
||||||
|
template <class Archive> struct specialize<Archive, Slic3r::ModelConfig, cereal::specialization::member_serialize> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* slic3r_Model_hpp_ */
|
#endif /* slic3r_Model_hpp_ */
|
||||||
|
|
|
@ -1121,7 +1121,8 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar
|
||||||
, m_bed(bed)
|
, m_bed(bed)
|
||||||
, m_camera(camera)
|
, m_camera(camera)
|
||||||
, m_view_toolbar(view_toolbar)
|
, m_view_toolbar(view_toolbar)
|
||||||
, m_toolbar(GLToolbar::Normal, "Top")
|
, m_main_toolbar(GLToolbar::Normal, "Top")
|
||||||
|
, m_undoredo_toolbar(GLToolbar::Normal, "Top")
|
||||||
, m_gizmos(*this)
|
, m_gizmos(*this)
|
||||||
, m_use_clipping_planes(false)
|
, m_use_clipping_planes(false)
|
||||||
, m_sidebar_field("")
|
, m_sidebar_field("")
|
||||||
|
@ -1228,7 +1229,7 @@ bool GLCanvas3D::init()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_toolbar.is_enabled() && !m_layers_editing.init("variable_layer_height.vs", "variable_layer_height.fs"))
|
if (m_main_toolbar.is_enabled() && !m_layers_editing.init("variable_layer_height.vs", "variable_layer_height.fs"))
|
||||||
{
|
{
|
||||||
std::cout << "Unable to initialize variable_layer_height shader: please, check that the files variable_layer_height.vs and variable_layer_height.fs are available" << std::endl;
|
std::cout << "Unable to initialize variable_layer_height shader: please, check that the files variable_layer_height.vs and variable_layer_height.fs are available" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -1242,7 +1243,7 @@ bool GLCanvas3D::init()
|
||||||
if (m_gizmos.is_enabled() && !m_gizmos.init())
|
if (m_gizmos.is_enabled() && !m_gizmos.init())
|
||||||
std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl;
|
std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl;
|
||||||
|
|
||||||
if (!_init_toolbar())
|
if (!_init_toolbars())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_selection.is_enabled() && !m_selection.init())
|
if (m_selection.is_enabled() && !m_selection.init())
|
||||||
|
@ -1433,9 +1434,14 @@ void GLCanvas3D::enable_selection(bool enable)
|
||||||
m_selection.set_enabled(enable);
|
m_selection.set_enabled(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::enable_toolbar(bool enable)
|
void GLCanvas3D::enable_main_toolbar(bool enable)
|
||||||
{
|
{
|
||||||
m_toolbar.set_enabled(enable);
|
m_main_toolbar.set_enabled(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::enable_undoredo_toolbar(bool enable)
|
||||||
|
{
|
||||||
|
m_undoredo_toolbar.set_enabled(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::enable_dynamic_background(bool enable)
|
void GLCanvas3D::enable_dynamic_background(bool enable)
|
||||||
|
@ -1771,6 +1777,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
PrinterTechnology printer_technology = m_process->current_printer_technology();
|
PrinterTechnology printer_technology = m_process->current_printer_technology();
|
||||||
int volume_idx_wipe_tower_old = -1;
|
int volume_idx_wipe_tower_old = -1;
|
||||||
|
|
||||||
|
if (printer_technology == ptSLA)
|
||||||
|
// Always do the full refresh in SLA mode to show / hide SLA support structures when an object is moved outside / inside the build volume.
|
||||||
|
m_regenerate_volumes = true;
|
||||||
|
|
||||||
if (m_regenerate_volumes)
|
if (m_regenerate_volumes)
|
||||||
{
|
{
|
||||||
// Release invalidated volumes to conserve GPU memory in case of delayed refresh (see m_reload_delayed).
|
// Release invalidated volumes to conserve GPU memory in case of delayed refresh (see m_reload_delayed).
|
||||||
|
@ -1803,7 +1813,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
state.step[istep].state = PrintStateBase::INVALID;
|
state.step[istep].state = PrintStateBase::INVALID;
|
||||||
else
|
else
|
||||||
for (const ModelInstance *model_instance : print_object->model_object()->instances)
|
for (const ModelInstance *model_instance : print_object->model_object()->instances)
|
||||||
aux_volume_state.emplace_back(state.step[istep].timestamp, model_instance->id());
|
// Only the instances, which are currently printable, will have the SLA support structures kept.
|
||||||
|
// The instances outside the print bed will have the GLVolumes of their support structures released.
|
||||||
|
if (model_instance->is_printable())
|
||||||
|
aux_volume_state.emplace_back(state.step[istep].timestamp, model_instance->id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sla_support_state.emplace_back(state);
|
sla_support_state.emplace_back(state);
|
||||||
|
@ -1955,7 +1968,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||||
|
|
||||||
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
|
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
|
||||||
for (GLVolume* volume : m_volumes.volumes)
|
for (GLVolume* volume : m_volumes.volumes)
|
||||||
volume->set_sla_shift_z(shift_zs[volume->object_idx()]);
|
if (volume->object_idx() < m_model->objects.size() && m_model->objects[volume->object_idx()]->instances[volume->instance_idx()]->is_printable())
|
||||||
|
volume->set_sla_shift_z(shift_zs[volume->object_idx()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (printer_technology == ptFFF && m_config->has("nozzle_diameter"))
|
if (printer_technology == ptFFF && m_config->has("nozzle_diameter"))
|
||||||
|
@ -2111,7 +2125,8 @@ void GLCanvas3D::load_sla_preview()
|
||||||
if ((m_canvas != nullptr) && (print != nullptr))
|
if ((m_canvas != nullptr) && (print != nullptr))
|
||||||
{
|
{
|
||||||
_set_current();
|
_set_current();
|
||||||
_load_sla_shells();
|
// Reload the SLA support structures into GLVolumes.
|
||||||
|
this->reload_scene(true, true);
|
||||||
_update_sla_shells_outside_state();
|
_update_sla_shells_outside_state();
|
||||||
_show_warning_texture_if_needed(WarningTexture::SlaSupportsOutside);
|
_show_warning_texture_if_needed(WarningTexture::SlaSupportsOutside);
|
||||||
}
|
}
|
||||||
|
@ -2214,7 +2229,8 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
|
||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_dirty |= m_toolbar.update_items_state();
|
m_dirty |= m_main_toolbar.update_items_state();
|
||||||
|
m_dirty |= m_undoredo_toolbar.update_items_state();
|
||||||
m_dirty |= m_view_toolbar.update_items_state();
|
m_dirty |= m_view_toolbar.update_items_state();
|
||||||
|
|
||||||
if (!m_dirty)
|
if (!m_dirty)
|
||||||
|
@ -2593,7 +2609,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||||
#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
|
#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_toolbar.on_mouse(evt, *this))
|
if (m_main_toolbar.on_mouse(evt, *this))
|
||||||
|
{
|
||||||
|
if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
|
||||||
|
mouse_up_cleanup();
|
||||||
|
m_mouse.set_start_position_3D_as_invalid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_undoredo_toolbar.on_mouse(evt, *this))
|
||||||
{
|
{
|
||||||
if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
|
if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
|
||||||
mouse_up_cleanup();
|
mouse_up_cleanup();
|
||||||
|
@ -2928,13 +2952,16 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||||
else if (evt.Moving())
|
else if (evt.Moving())
|
||||||
{
|
{
|
||||||
m_mouse.position = pos.cast<double>();
|
m_mouse.position = pos.cast<double>();
|
||||||
std::string tooltip = "";
|
std::string tooltip = L("");
|
||||||
|
|
||||||
if (tooltip.empty())
|
if (tooltip.empty())
|
||||||
tooltip = m_gizmos.get_tooltip();
|
tooltip = m_gizmos.get_tooltip();
|
||||||
|
|
||||||
if (tooltip.empty())
|
if (tooltip.empty())
|
||||||
tooltip = m_toolbar.get_tooltip();
|
tooltip = m_main_toolbar.get_tooltip();
|
||||||
|
|
||||||
|
if (tooltip.empty())
|
||||||
|
tooltip = m_undoredo_toolbar.get_tooltip();
|
||||||
|
|
||||||
if (tooltip.empty())
|
if (tooltip.empty())
|
||||||
tooltip = m_view_toolbar.get_tooltip();
|
tooltip = m_view_toolbar.get_tooltip();
|
||||||
|
@ -3399,16 +3426,19 @@ void GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x)
|
||||||
ImGuiWrapper* imgui = wxGetApp().imgui();
|
ImGuiWrapper* imgui = wxGetApp().imgui();
|
||||||
|
|
||||||
const float x = pos_x * (float)get_camera().get_zoom() + 0.5f * (float)get_canvas_size().get_width();
|
const float x = pos_x * (float)get_camera().get_zoom() + 0.5f * (float)get_canvas_size().get_width();
|
||||||
imgui->set_next_window_pos(x, m_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f);
|
imgui->set_next_window_pos(x, m_undoredo_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f);
|
||||||
imgui->set_next_window_bg_alpha(0.5f);
|
imgui->set_next_window_bg_alpha(0.5f);
|
||||||
imgui->begin(wxString::Format(_(L("%s Stack")), stack_name),
|
imgui->begin(wxString::Format(_(L("%s Stack")), stack_name),
|
||||||
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||||
|
|
||||||
int hovered = m_imgui_undo_redo_hovered_pos;
|
int hovered = m_imgui_undo_redo_hovered_pos;
|
||||||
int selected = -1;
|
int selected = -1;
|
||||||
const float em = static_cast<float>(wxGetApp().em_unit());
|
float em = static_cast<float>(wxGetApp().em_unit());
|
||||||
|
#if ENABLE_RETINA_GL
|
||||||
|
em *= m_retina_helper->get_scale_factor();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (imgui->undo_redo_list(ImVec2(12 * em, 20 * em), is_undo, &string_getter, hovered, selected))
|
if (imgui->undo_redo_list(ImVec2(18 * em, 26 * em), is_undo, &string_getter, hovered, selected))
|
||||||
m_imgui_undo_redo_hovered_pos = hovered;
|
m_imgui_undo_redo_hovered_pos = hovered;
|
||||||
else
|
else
|
||||||
m_imgui_undo_redo_hovered_pos = -1;
|
m_imgui_undo_redo_hovered_pos = -1;
|
||||||
|
@ -3421,9 +3451,20 @@ void GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x)
|
||||||
imgui->end();
|
imgui->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLCanvas3D::_init_toolbar()
|
bool GLCanvas3D::_init_toolbars()
|
||||||
{
|
{
|
||||||
if (!m_toolbar.is_enabled())
|
if (!_init_main_toolbar())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_init_undoredo_toolbar())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLCanvas3D::_init_main_toolbar()
|
||||||
|
{
|
||||||
|
if (!m_main_toolbar.is_enabled())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
BackgroundTexture::Metadata background_data;
|
BackgroundTexture::Metadata background_data;
|
||||||
|
@ -3433,19 +3474,20 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
background_data.right = 16;
|
background_data.right = 16;
|
||||||
background_data.bottom = 16;
|
background_data.bottom = 16;
|
||||||
|
|
||||||
if (!m_toolbar.init(background_data))
|
if (!m_main_toolbar.init(background_data))
|
||||||
{
|
{
|
||||||
// unable to init the toolbar texture, disable it
|
// unable to init the toolbar texture, disable it
|
||||||
m_toolbar.set_enabled(false);
|
m_main_toolbar.set_enabled(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_toolbar.set_layout_type(GLToolbar::Layout::Vertical);
|
// m_main_toolbar.set_layout_type(GLToolbar::Layout::Vertical);
|
||||||
m_toolbar.set_layout_type(GLToolbar::Layout::Horizontal);
|
m_main_toolbar.set_layout_type(GLToolbar::Layout::Horizontal);
|
||||||
m_toolbar.set_layout_orientation(GLToolbar::Layout::Top);
|
m_main_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Right);
|
||||||
m_toolbar.set_border(5.0f);
|
m_main_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Top);
|
||||||
m_toolbar.set_separator_size(5);
|
m_main_toolbar.set_border(5.0f);
|
||||||
m_toolbar.set_gap_size(2);
|
m_main_toolbar.set_separator_size(5);
|
||||||
|
m_main_toolbar.set_gap_size(2);
|
||||||
|
|
||||||
GLToolbarItem::Data item;
|
GLToolbarItem::Data item;
|
||||||
|
|
||||||
|
@ -3454,7 +3496,7 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
item.tooltip = _utf8(L("Add...")) + " [" + GUI::shortkey_ctrl_prefix() + "I]";
|
item.tooltip = _utf8(L("Add...")) + " [" + GUI::shortkey_ctrl_prefix() + "I]";
|
||||||
item.sprite_id = 0;
|
item.sprite_id = 0;
|
||||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD)); };
|
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD)); };
|
||||||
if (!m_toolbar.add_item(item))
|
if (!m_main_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item.name = "delete";
|
item.name = "delete";
|
||||||
|
@ -3463,7 +3505,7 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
item.sprite_id = 1;
|
item.sprite_id = 1;
|
||||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE)); };
|
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE)); };
|
||||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_delete(); };
|
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_delete(); };
|
||||||
if (!m_toolbar.add_item(item))
|
if (!m_main_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item.name = "deleteall";
|
item.name = "deleteall";
|
||||||
|
@ -3472,7 +3514,7 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
item.sprite_id = 2;
|
item.sprite_id = 2;
|
||||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); };
|
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); };
|
||||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_delete_all(); };
|
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_delete_all(); };
|
||||||
if (!m_toolbar.add_item(item))
|
if (!m_main_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item.name = "arrange";
|
item.name = "arrange";
|
||||||
|
@ -3481,10 +3523,10 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
item.sprite_id = 3;
|
item.sprite_id = 3;
|
||||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ARRANGE)); };
|
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ARRANGE)); };
|
||||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
|
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
|
||||||
if (!m_toolbar.add_item(item))
|
if (!m_main_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_toolbar.add_separator())
|
if (!m_main_toolbar.add_separator())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item.name = "copy";
|
item.name = "copy";
|
||||||
|
@ -3493,7 +3535,7 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
item.sprite_id = 4;
|
item.sprite_id = 4;
|
||||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_COPY)); };
|
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_COPY)); };
|
||||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_copy_to_clipboard(); };
|
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_copy_to_clipboard(); };
|
||||||
if (!m_toolbar.add_item(item))
|
if (!m_main_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item.name = "paste";
|
item.name = "paste";
|
||||||
|
@ -3502,10 +3544,10 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
item.sprite_id = 5;
|
item.sprite_id = 5;
|
||||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_PASTE)); };
|
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_PASTE)); };
|
||||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_paste_from_clipboard(); };
|
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_paste_from_clipboard(); };
|
||||||
if (!m_toolbar.add_item(item))
|
if (!m_main_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_toolbar.add_separator())
|
if (!m_main_toolbar.add_separator())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item.name = "more";
|
item.name = "more";
|
||||||
|
@ -3516,7 +3558,7 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
|
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
|
||||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); };
|
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); };
|
||||||
|
|
||||||
if (!m_toolbar.add_item(item))
|
if (!m_main_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item.name = "fewer";
|
item.name = "fewer";
|
||||||
|
@ -3526,10 +3568,10 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); };
|
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); };
|
||||||
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
|
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
|
||||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); };
|
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); };
|
||||||
if (!m_toolbar.add_item(item))
|
if (!m_main_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_toolbar.add_separator())
|
if (!m_main_toolbar.add_separator())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item.name = "splitobjects";
|
item.name = "splitobjects";
|
||||||
|
@ -3539,7 +3581,7 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
|
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
|
||||||
item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
|
item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
|
||||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
|
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
|
||||||
if (!m_toolbar.add_item(item))
|
if (!m_main_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item.name = "splitvolumes";
|
item.name = "splitvolumes";
|
||||||
|
@ -3549,10 +3591,10 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); };
|
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); };
|
||||||
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
|
item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
|
||||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); };
|
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); };
|
||||||
if (!m_toolbar.add_item(item))
|
if (!m_main_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_toolbar.add_separator())
|
if (!m_main_toolbar.add_separator())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item.name = "layersediting";
|
item.name = "layersediting";
|
||||||
|
@ -3563,35 +3605,98 @@ bool GLCanvas3D::_init_toolbar()
|
||||||
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); };
|
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); };
|
||||||
item.visibility_callback = [this]()->bool { return m_process->current_printer_technology() == ptFFF; };
|
item.visibility_callback = [this]()->bool { return m_process->current_printer_technology() == ptFFF; };
|
||||||
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_layers_editing(); };
|
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_layers_editing(); };
|
||||||
if (!m_toolbar.add_item(item))
|
if (!m_main_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!m_toolbar.add_separator())
|
return true;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
bool GLCanvas3D::_init_undoredo_toolbar()
|
||||||
|
{
|
||||||
|
if (!m_undoredo_toolbar.is_enabled())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
BackgroundTexture::Metadata background_data;
|
||||||
|
background_data.filename = "toolbar_background.png";
|
||||||
|
background_data.left = 16;
|
||||||
|
background_data.top = 16;
|
||||||
|
background_data.right = 16;
|
||||||
|
background_data.bottom = 16;
|
||||||
|
|
||||||
|
if (!m_undoredo_toolbar.init(background_data))
|
||||||
|
{
|
||||||
|
// unable to init the toolbar texture, disable it
|
||||||
|
m_undoredo_toolbar.set_enabled(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_undoredo_toolbar.set_layout_type(GLToolbar::Layout::Vertical);
|
||||||
|
m_undoredo_toolbar.set_layout_type(GLToolbar::Layout::Horizontal);
|
||||||
|
m_undoredo_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Left);
|
||||||
|
m_undoredo_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Top);
|
||||||
|
m_undoredo_toolbar.set_border(5.0f);
|
||||||
|
m_undoredo_toolbar.set_separator_size(5);
|
||||||
|
m_undoredo_toolbar.set_gap_size(2);
|
||||||
|
|
||||||
|
GLToolbarItem::Data item;
|
||||||
|
|
||||||
item.name = "undo";
|
item.name = "undo";
|
||||||
item.icon_filename = "undo_toolbar.svg";
|
item.icon_filename = "undo_toolbar.svg";
|
||||||
item.tooltip = _utf8(L("Undo")) + " [" + GUI::shortkey_ctrl_prefix() + "Z]";
|
item.tooltip = _utf8(L("Undo")) + " [" + GUI::shortkey_ctrl_prefix() + "Z]";
|
||||||
item.sprite_id = 11;
|
item.sprite_id = 0;
|
||||||
item.left.toggable = false;
|
|
||||||
item.left.action_callback = [this]() { post_event(SimpleEvent(EVT_GLCANVAS_UNDO)); };
|
item.left.action_callback = [this]() { post_event(SimpleEvent(EVT_GLCANVAS_UNDO)); };
|
||||||
item.right.toggable = true;
|
item.right.toggable = true;
|
||||||
item.right.action_callback = [this]() { m_imgui_undo_redo_hovered_pos = -1; };
|
item.right.action_callback = [this]() { m_imgui_undo_redo_hovered_pos = -1; };
|
||||||
item.right.render_callback = [this](float left, float right, float, float) { if (m_canvas != nullptr) _render_undo_redo_stack(true, 0.5f * (left + right)); };
|
item.right.render_callback = [this](float left, float right, float, float) { if (m_canvas != nullptr) _render_undo_redo_stack(true, 0.5f * (left + right)); };
|
||||||
item.visibility_callback = []()->bool { return true; };
|
item.enabling_callback = [this]()->bool {
|
||||||
item.enabling_callback = [this]()->bool { return wxGetApp().plater()->can_undo(); };
|
bool can_undo = wxGetApp().plater()->can_undo();
|
||||||
if (!m_toolbar.add_item(item))
|
unsigned int id = m_undoredo_toolbar.get_item_id("undo");
|
||||||
|
|
||||||
|
std::string curr_additional_tooltip;
|
||||||
|
m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip);
|
||||||
|
|
||||||
|
std::string new_additional_tooltip = L("");
|
||||||
|
if (can_undo)
|
||||||
|
wxGetApp().plater()->undo_redo_topmost_string_getter(true, new_additional_tooltip);
|
||||||
|
|
||||||
|
if (new_additional_tooltip != curr_additional_tooltip)
|
||||||
|
{
|
||||||
|
m_undoredo_toolbar.set_additional_tooltip(id, new_additional_tooltip);
|
||||||
|
set_tooltip(L(""));
|
||||||
|
}
|
||||||
|
return can_undo;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!m_undoredo_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item.name = "redo";
|
item.name = "redo";
|
||||||
item.icon_filename = "redo_toolbar.svg";
|
item.icon_filename = "redo_toolbar.svg";
|
||||||
item.tooltip = _utf8(L("Redo")) + " [" + GUI::shortkey_ctrl_prefix() + "Y]";
|
item.tooltip = _utf8(L("Redo")) + " [" + GUI::shortkey_ctrl_prefix() + "Y]";
|
||||||
item.sprite_id = 12;
|
item.sprite_id = 1;
|
||||||
item.left.action_callback = [this]() { post_event(SimpleEvent(EVT_GLCANVAS_REDO)); };
|
item.left.action_callback = [this]() { post_event(SimpleEvent(EVT_GLCANVAS_REDO)); };
|
||||||
item.right.action_callback = [this]() { m_imgui_undo_redo_hovered_pos = -1; };
|
item.right.action_callback = [this]() { m_imgui_undo_redo_hovered_pos = -1; };
|
||||||
item.right.render_callback = [this](float left, float right, float, float) { if (m_canvas != nullptr) _render_undo_redo_stack(false, 0.5f * (left + right)); };
|
item.right.render_callback = [this](float left, float right, float, float) { if (m_canvas != nullptr) _render_undo_redo_stack(false, 0.5f * (left + right)); };
|
||||||
item.enabling_callback = [this]()->bool { return wxGetApp().plater()->can_redo(); };
|
item.enabling_callback = [this]()->bool {
|
||||||
if (!m_toolbar.add_item(item))
|
bool can_redo = wxGetApp().plater()->can_redo();
|
||||||
|
unsigned int id = m_undoredo_toolbar.get_item_id("redo");
|
||||||
|
|
||||||
|
std::string curr_additional_tooltip;
|
||||||
|
m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip);
|
||||||
|
|
||||||
|
std::string new_additional_tooltip = L("");
|
||||||
|
if (can_redo)
|
||||||
|
wxGetApp().plater()->undo_redo_topmost_string_getter(false, new_additional_tooltip);
|
||||||
|
|
||||||
|
if (new_additional_tooltip != curr_additional_tooltip)
|
||||||
|
{
|
||||||
|
m_undoredo_toolbar.set_additional_tooltip(id, new_additional_tooltip);
|
||||||
|
set_tooltip(L(""));
|
||||||
|
}
|
||||||
|
return can_redo;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!m_undoredo_toolbar.add_item(item))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -3918,7 +4023,8 @@ void GLCanvas3D::_render_overlays() const
|
||||||
_render_gizmos_overlay();
|
_render_gizmos_overlay();
|
||||||
_render_warning_texture();
|
_render_warning_texture();
|
||||||
_render_legend_texture();
|
_render_legend_texture();
|
||||||
_render_toolbar();
|
_render_main_toolbar();
|
||||||
|
_render_undoredo_toolbar();
|
||||||
_render_view_toolbar();
|
_render_view_toolbar();
|
||||||
|
|
||||||
if ((m_layers_editing.last_object_id >= 0) && (m_layers_editing.object_max_z() > 0.0f))
|
if ((m_layers_editing.last_object_id >= 0) && (m_layers_editing.object_max_z() > 0.0f))
|
||||||
|
@ -4008,64 +4114,57 @@ void GLCanvas3D::_render_gizmos_overlay() const
|
||||||
m_gizmos.render_overlay();
|
m_gizmos.render_overlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::_render_toolbar() const
|
void GLCanvas3D::_render_main_toolbar() const
|
||||||
{
|
{
|
||||||
|
if (!m_main_toolbar.is_enabled())
|
||||||
|
return;
|
||||||
|
|
||||||
#if ENABLE_RETINA_GL
|
#if ENABLE_RETINA_GL
|
||||||
// m_toolbar.set_scale(m_retina_helper->get_scale_factor());
|
// m_main_toolbar.set_scale(m_retina_helper->get_scale_factor());
|
||||||
const float scale = m_retina_helper->get_scale_factor() * wxGetApp().toolbar_icon_scale(true);
|
const float scale = m_retina_helper->get_scale_factor() * wxGetApp().toolbar_icon_scale(true);
|
||||||
m_toolbar.set_scale(scale); //! #ys_FIXME_experiment
|
m_main_toolbar.set_scale(scale); //! #ys_FIXME_experiment
|
||||||
#else
|
#else
|
||||||
// m_toolbar.set_scale(m_canvas->GetContentScaleFactor());
|
// m_main_toolbar.set_scale(m_canvas->GetContentScaleFactor());
|
||||||
// m_toolbar.set_scale(wxGetApp().em_unit()*0.1f);
|
// m_main_toolbar.set_scale(wxGetApp().em_unit()*0.1f);
|
||||||
const float size = int(GLToolbar::Default_Icons_Size * wxGetApp().toolbar_icon_scale(true));
|
const float size = int(GLToolbar::Default_Icons_Size * wxGetApp().toolbar_icon_scale(true));
|
||||||
m_toolbar.set_icons_size(size); //! #ys_FIXME_experiment
|
m_main_toolbar.set_icons_size(size); //! #ys_FIXME_experiment
|
||||||
#endif // ENABLE_RETINA_GL
|
#endif // ENABLE_RETINA_GL
|
||||||
|
|
||||||
Size cnv_size = get_canvas_size();
|
Size cnv_size = get_canvas_size();
|
||||||
float zoom = (float)m_camera.get_zoom();
|
float zoom = (float)m_camera.get_zoom();
|
||||||
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
||||||
|
|
||||||
GLToolbar::Layout::EOrientation orientation = m_toolbar.get_layout_orientation();
|
float top = 0.5f * (float)cnv_size.get_height() * inv_zoom;
|
||||||
|
float left = -0.5f * (m_main_toolbar.get_width() + m_undoredo_toolbar.get_width()) * inv_zoom;
|
||||||
|
|
||||||
float top = 0.0f;
|
m_main_toolbar.set_position(top, left);
|
||||||
float left = 0.0f;
|
m_main_toolbar.render(*this);
|
||||||
switch (m_toolbar.get_layout_type())
|
}
|
||||||
{
|
|
||||||
default:
|
|
||||||
case GLToolbar::Layout::Horizontal:
|
|
||||||
{
|
|
||||||
// centers the toolbar on the top edge of the 3d scene
|
|
||||||
if (orientation == GLToolbar::Layout::Top)
|
|
||||||
{
|
|
||||||
top = 0.5f * (float)cnv_size.get_height() * inv_zoom;
|
|
||||||
left = -0.5f * m_toolbar.get_width() * inv_zoom;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
top = (-0.5f * (float)cnv_size.get_height() + m_view_toolbar.get_height()) * inv_zoom;
|
|
||||||
left = -0.5f * m_toolbar.get_width() * inv_zoom;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GLToolbar::Layout::Vertical:
|
|
||||||
{
|
|
||||||
// centers the toolbar on the right edge of the 3d scene
|
|
||||||
if (orientation == GLToolbar::Layout::Left)
|
|
||||||
{
|
|
||||||
top = 0.5f * m_toolbar.get_height() * inv_zoom;
|
|
||||||
left = (-0.5f * (float)cnv_size.get_width()) * inv_zoom;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
top = 0.5f * m_toolbar.get_height() * inv_zoom;
|
|
||||||
left = (0.5f * (float)cnv_size.get_width() - m_toolbar.get_width()) * inv_zoom;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_toolbar.set_position(top, left);
|
|
||||||
|
|
||||||
m_toolbar.render(*this);
|
void GLCanvas3D::_render_undoredo_toolbar() const
|
||||||
|
{
|
||||||
|
if (!m_undoredo_toolbar.is_enabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if ENABLE_RETINA_GL
|
||||||
|
// m_undoredo_toolbar.set_scale(m_retina_helper->get_scale_factor());
|
||||||
|
const float scale = m_retina_helper->get_scale_factor() * wxGetApp().toolbar_icon_scale(true);
|
||||||
|
m_undoredo_toolbar.set_scale(scale); //! #ys_FIXME_experiment
|
||||||
|
#else
|
||||||
|
// m_undoredo_toolbar.set_scale(m_canvas->GetContentScaleFactor());
|
||||||
|
// m_undoredo_toolbar.set_scale(wxGetApp().em_unit()*0.1f);
|
||||||
|
const float size = int(GLToolbar::Default_Icons_Size * wxGetApp().toolbar_icon_scale(true));
|
||||||
|
m_undoredo_toolbar.set_icons_size(size); //! #ys_FIXME_experiment
|
||||||
|
#endif // ENABLE_RETINA_GL
|
||||||
|
|
||||||
|
Size cnv_size = get_canvas_size();
|
||||||
|
float zoom = (float)m_camera.get_zoom();
|
||||||
|
float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
|
||||||
|
|
||||||
|
float top = 0.5f * (float)cnv_size.get_height() * inv_zoom;
|
||||||
|
float left = (m_main_toolbar.get_width() - 0.5f * (m_main_toolbar.get_width() + m_undoredo_toolbar.get_width())) * inv_zoom;
|
||||||
|
m_undoredo_toolbar.set_position(top, left);
|
||||||
|
m_undoredo_toolbar.render(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::_render_view_toolbar() const
|
void GLCanvas3D::_render_view_toolbar() const
|
||||||
|
@ -5322,56 +5421,6 @@ void GLCanvas3D::_load_fff_shells()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::_load_sla_shells()
|
|
||||||
{
|
|
||||||
//FIXME use reload_scene
|
|
||||||
#if 1
|
|
||||||
const SLAPrint* print = this->sla_print();
|
|
||||||
if (print->objects().empty())
|
|
||||||
// nothing to render, return
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto add_volume = [this](const SLAPrintObject &object, int volume_id, const SLAPrintObject::Instance& instance,
|
|
||||||
const TriangleMesh &mesh, const float color[4], bool outside_printer_detection_enabled) {
|
|
||||||
m_volumes.volumes.emplace_back(new GLVolume(color));
|
|
||||||
GLVolume& v = *m_volumes.volumes.back();
|
|
||||||
v.indexed_vertex_array.load_mesh(mesh);
|
|
||||||
v.shader_outside_printer_detection_enabled = outside_printer_detection_enabled;
|
|
||||||
v.composite_id.volume_id = volume_id;
|
|
||||||
v.set_instance_offset(unscale(instance.shift(0), instance.shift(1), 0));
|
|
||||||
v.set_instance_rotation(Vec3d(0.0, 0.0, (double)instance.rotation));
|
|
||||||
v.set_instance_mirror(X, object.is_left_handed() ? -1. : 1.);
|
|
||||||
v.set_convex_hull(mesh.convex_hull_3d());
|
|
||||||
};
|
|
||||||
|
|
||||||
// adds objects' volumes
|
|
||||||
for (const SLAPrintObject* obj : print->objects())
|
|
||||||
if (obj->is_step_done(slaposSliceSupports)) {
|
|
||||||
unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size();
|
|
||||||
for (const SLAPrintObject::Instance& instance : obj->instances()) {
|
|
||||||
add_volume(*obj, 0, instance, obj->transformed_mesh(), GLVolume::MODEL_COLOR[0], true);
|
|
||||||
// Set the extruder_id and volume_id to achieve the same color as in the 3D scene when
|
|
||||||
// through the update_volumes_colors_by_extruder() call.
|
|
||||||
m_volumes.volumes.back()->extruder_id = obj->model_object()->volumes.front()->extruder_id();
|
|
||||||
if (obj->is_step_done(slaposSupportTree) && obj->has_mesh(slaposSupportTree))
|
|
||||||
add_volume(*obj, -int(slaposSupportTree), instance, obj->support_mesh(), GLVolume::SLA_SUPPORT_COLOR, true);
|
|
||||||
if (obj->is_step_done(slaposBasePool) && obj->has_mesh(slaposBasePool))
|
|
||||||
add_volume(*obj, -int(slaposBasePool), instance, obj->pad_mesh(), GLVolume::SLA_PAD_COLOR, false);
|
|
||||||
}
|
|
||||||
double shift_z = obj->get_current_elevation();
|
|
||||||
for (unsigned int i = initial_volumes_count; i < m_volumes.volumes.size(); ++ i) {
|
|
||||||
GLVolume& v = *m_volumes.volumes[i];
|
|
||||||
// apply shift z
|
|
||||||
v.set_sla_shift_z(shift_z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
update_volumes_colors_by_extruder();
|
|
||||||
#else
|
|
||||||
this->reload_scene(true, true);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLCanvas3D::_update_gcode_volumes_visibility(const GCodePreviewData& preview_data)
|
void GLCanvas3D::_update_gcode_volumes_visibility(const GCodePreviewData& preview_data)
|
||||||
{
|
{
|
||||||
unsigned int size = (unsigned int)m_gcode_preview_volume_index.first_volumes.size();
|
unsigned int size = (unsigned int)m_gcode_preview_volume_index.first_volumes.size();
|
||||||
|
@ -5587,14 +5636,14 @@ void GLCanvas3D::_update_selection_from_hover()
|
||||||
|
|
||||||
bool GLCanvas3D::_deactivate_undo_redo_toolbar_items()
|
bool GLCanvas3D::_deactivate_undo_redo_toolbar_items()
|
||||||
{
|
{
|
||||||
if (m_toolbar.is_item_pressed("undo"))
|
if (m_undoredo_toolbar.is_item_pressed("undo"))
|
||||||
{
|
{
|
||||||
m_toolbar.force_right_action(m_toolbar.get_item_id("undo"), *this);
|
m_undoredo_toolbar.force_right_action(m_undoredo_toolbar.get_item_id("undo"), *this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (m_toolbar.is_item_pressed("redo"))
|
else if (m_undoredo_toolbar.is_item_pressed("redo"))
|
||||||
{
|
{
|
||||||
m_toolbar.force_right_action(m_toolbar.get_item_id("redo"), *this);
|
m_undoredo_toolbar.force_right_action(m_undoredo_toolbar.get_item_id("redo"), *this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -412,7 +412,8 @@ private:
|
||||||
Shader m_shader;
|
Shader m_shader;
|
||||||
Mouse m_mouse;
|
Mouse m_mouse;
|
||||||
mutable GLGizmosManager m_gizmos;
|
mutable GLGizmosManager m_gizmos;
|
||||||
mutable GLToolbar m_toolbar;
|
mutable GLToolbar m_main_toolbar;
|
||||||
|
mutable GLToolbar m_undoredo_toolbar;
|
||||||
ClippingPlane m_clipping_planes[2];
|
ClippingPlane m_clipping_planes[2];
|
||||||
mutable ClippingPlane m_camera_clipping_plane;
|
mutable ClippingPlane m_camera_clipping_plane;
|
||||||
bool m_use_clipping_planes;
|
bool m_use_clipping_planes;
|
||||||
|
@ -525,7 +526,8 @@ public:
|
||||||
void enable_moving(bool enable);
|
void enable_moving(bool enable);
|
||||||
void enable_gizmos(bool enable);
|
void enable_gizmos(bool enable);
|
||||||
void enable_selection(bool enable);
|
void enable_selection(bool enable);
|
||||||
void enable_toolbar(bool enable);
|
void enable_main_toolbar(bool enable);
|
||||||
|
void enable_undoredo_toolbar(bool enable);
|
||||||
void enable_dynamic_background(bool enable);
|
void enable_dynamic_background(bool enable);
|
||||||
void allow_multisample(bool allow);
|
void allow_multisample(bool allow);
|
||||||
|
|
||||||
|
@ -618,10 +620,18 @@ public:
|
||||||
void start_keeping_dirty() { m_keep_dirty = true; }
|
void start_keeping_dirty() { m_keep_dirty = true; }
|
||||||
void stop_keeping_dirty() { m_keep_dirty = false; }
|
void stop_keeping_dirty() { m_keep_dirty = false; }
|
||||||
|
|
||||||
|
unsigned int get_main_toolbar_item_id(const std::string& name) const { return m_main_toolbar.get_item_id(name); }
|
||||||
|
void force_main_toolbar_left_action(unsigned int item_id) { m_main_toolbar.force_left_action(item_id, *this); }
|
||||||
|
void force_main_toolbar_right_action(unsigned int item_id) { m_main_toolbar.force_right_action(item_id, *this); }
|
||||||
|
void get_undoredo_toolbar_additional_tooltip(unsigned int item_id, std::string& text) { return m_undoredo_toolbar.get_additional_tooltip(item_id, text); }
|
||||||
|
void set_undoredo_toolbar_additional_tooltip(unsigned int item_id, const std::string& text) { m_undoredo_toolbar.set_additional_tooltip(item_id, text); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _is_shown_on_screen() const;
|
bool _is_shown_on_screen() const;
|
||||||
|
|
||||||
bool _init_toolbar();
|
bool _init_toolbars();
|
||||||
|
bool _init_main_toolbar();
|
||||||
|
bool _init_undoredo_toolbar();
|
||||||
|
|
||||||
bool _set_current();
|
bool _set_current();
|
||||||
void _resize(unsigned int w, unsigned int h);
|
void _resize(unsigned int w, unsigned int h);
|
||||||
|
@ -648,7 +658,8 @@ private:
|
||||||
void _render_volumes_for_picking() const;
|
void _render_volumes_for_picking() const;
|
||||||
void _render_current_gizmo() const;
|
void _render_current_gizmo() const;
|
||||||
void _render_gizmos_overlay() const;
|
void _render_gizmos_overlay() const;
|
||||||
void _render_toolbar() const;
|
void _render_main_toolbar() const;
|
||||||
|
void _render_undoredo_toolbar() const;
|
||||||
void _render_view_toolbar() const;
|
void _render_view_toolbar() const;
|
||||||
#if ENABLE_SHOW_CAMERA_TARGET
|
#if ENABLE_SHOW_CAMERA_TARGET
|
||||||
void _render_camera_target() const;
|
void _render_camera_target() const;
|
||||||
|
@ -695,8 +706,6 @@ private:
|
||||||
void _load_gcode_unretractions(const GCodePreviewData& preview_data);
|
void _load_gcode_unretractions(const GCodePreviewData& preview_data);
|
||||||
// generates objects and wipe tower geometry
|
// generates objects and wipe tower geometry
|
||||||
void _load_fff_shells();
|
void _load_fff_shells();
|
||||||
// generates objects geometry for sla
|
|
||||||
void _load_sla_shells();
|
|
||||||
// sets gcode geometry visibility according to user selection
|
// sets gcode geometry visibility according to user selection
|
||||||
void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
|
void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
|
||||||
void _update_toolpath_volumes_outside_state();
|
void _update_toolpath_volumes_outside_state();
|
||||||
|
|
|
@ -48,6 +48,7 @@ GLToolbarItem::Data::Data()
|
||||||
: name("")
|
: name("")
|
||||||
, icon_filename("")
|
, icon_filename("")
|
||||||
, tooltip("")
|
, tooltip("")
|
||||||
|
, additional_tooltip("")
|
||||||
, sprite_id(-1)
|
, sprite_id(-1)
|
||||||
, visible(true)
|
, visible(true)
|
||||||
, visibility_callback(Default_Visibility_Callback)
|
, visibility_callback(Default_Visibility_Callback)
|
||||||
|
@ -131,7 +132,8 @@ const float GLToolbar::Default_Icons_Size = 40.0f;
|
||||||
|
|
||||||
GLToolbar::Layout::Layout()
|
GLToolbar::Layout::Layout()
|
||||||
: type(Horizontal)
|
: type(Horizontal)
|
||||||
, orientation(Center)
|
, horizontal_orientation(HO_Center)
|
||||||
|
, vertical_orientation(VO_Center)
|
||||||
, top(0.0f)
|
, top(0.0f)
|
||||||
, left(0.0f)
|
, left(0.0f)
|
||||||
, border(0.0f)
|
, border(0.0f)
|
||||||
|
@ -191,16 +193,6 @@ void GLToolbar::set_layout_type(GLToolbar::Layout::EType type)
|
||||||
m_layout.dirty = true;
|
m_layout.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLToolbar::Layout::EOrientation GLToolbar::get_layout_orientation() const
|
|
||||||
{
|
|
||||||
return m_layout.orientation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLToolbar::set_layout_orientation(GLToolbar::Layout::EOrientation orientation)
|
|
||||||
{
|
|
||||||
m_layout.orientation = orientation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLToolbar::set_position(float top, float left)
|
void GLToolbar::set_position(float top, float left)
|
||||||
{
|
{
|
||||||
m_layout.top = top;
|
m_layout.top = top;
|
||||||
|
@ -374,6 +366,31 @@ void GLToolbar::force_right_action(unsigned int item_id, GLCanvas3D& parent)
|
||||||
do_action(GLToolbarItem::Right, item_id, parent, false);
|
do_action(GLToolbarItem::Right, item_id, parent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLToolbar::get_additional_tooltip(unsigned int item_id, std::string& text)
|
||||||
|
{
|
||||||
|
if (item_id < (unsigned int)m_items.size())
|
||||||
|
{
|
||||||
|
GLToolbarItem* item = m_items[item_id];
|
||||||
|
if (item != nullptr)
|
||||||
|
{
|
||||||
|
text = item->get_additional_tooltip();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text = L("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLToolbar::set_additional_tooltip(unsigned int item_id, const std::string& text)
|
||||||
|
{
|
||||||
|
if (item_id < (unsigned int)m_items.size())
|
||||||
|
{
|
||||||
|
GLToolbarItem* item = m_items[item_id];
|
||||||
|
if (item != nullptr)
|
||||||
|
item->set_additional_tooltip(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool GLToolbar::update_items_state()
|
bool GLToolbar::update_items_state()
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
@ -403,6 +420,9 @@ void GLToolbar::render(const GLCanvas3D& parent) const
|
||||||
|
|
||||||
bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
|
bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
|
||||||
{
|
{
|
||||||
|
if (!m_enabled)
|
||||||
|
return false;
|
||||||
|
|
||||||
Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY());
|
Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY());
|
||||||
bool processed = false;
|
bool processed = false;
|
||||||
|
|
||||||
|
@ -433,7 +453,7 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
|
||||||
if (item_id == -1)
|
if (item_id == -1)
|
||||||
{
|
{
|
||||||
// mouse is outside the toolbar
|
// mouse is outside the toolbar
|
||||||
m_tooltip = "";
|
m_tooltip = L("");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -600,7 +620,7 @@ void GLToolbar::do_action(GLToolbarItem::EActionType type, unsigned int item_id,
|
||||||
std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
|
std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
|
||||||
{
|
{
|
||||||
if (!m_enabled)
|
if (!m_enabled)
|
||||||
return "";
|
return L("");
|
||||||
|
|
||||||
switch (m_layout.type)
|
switch (m_layout.type)
|
||||||
{
|
{
|
||||||
|
@ -649,7 +669,15 @@ std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLC
|
||||||
GLToolbarItem::EState state = item->get_state();
|
GLToolbarItem::EState state = item->get_state();
|
||||||
bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top);
|
bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top);
|
||||||
if (inside)
|
if (inside)
|
||||||
|
{
|
||||||
tooltip = item->get_tooltip();
|
tooltip = item->get_tooltip();
|
||||||
|
if (!item->is_pressed())
|
||||||
|
{
|
||||||
|
const std::string& additional_tooltip = item->get_additional_tooltip();
|
||||||
|
if (!additional_tooltip.empty())
|
||||||
|
tooltip += L("\n") + additional_tooltip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
|
@ -745,7 +773,15 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
|
||||||
GLToolbarItem::EState state = item->get_state();
|
GLToolbarItem::EState state = item->get_state();
|
||||||
bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top);
|
bool inside = (left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top);
|
||||||
if (inside)
|
if (inside)
|
||||||
|
{
|
||||||
tooltip = item->get_tooltip();
|
tooltip = item->get_tooltip();
|
||||||
|
if (!item->is_pressed())
|
||||||
|
{
|
||||||
|
const std::string& additional_tooltip = item->get_additional_tooltip();
|
||||||
|
if (!additional_tooltip.empty())
|
||||||
|
tooltip += L("\n") + additional_tooltip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
|
@ -966,6 +1002,84 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLToolbar::render_background(float left, float top, float right, float bottom, float border) const
|
||||||
|
{
|
||||||
|
unsigned int tex_id = m_background_texture.texture.get_id();
|
||||||
|
float tex_width = (float)m_background_texture.texture.get_width();
|
||||||
|
float tex_height = (float)m_background_texture.texture.get_height();
|
||||||
|
if ((tex_id != 0) && (tex_width > 0) && (tex_height > 0))
|
||||||
|
{
|
||||||
|
float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f;
|
||||||
|
float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f;
|
||||||
|
|
||||||
|
float internal_left = left + border;
|
||||||
|
float internal_right = right - border;
|
||||||
|
float internal_top = top - border;
|
||||||
|
float internal_bottom = bottom + border;
|
||||||
|
|
||||||
|
float left_uv = 0.0f;
|
||||||
|
float right_uv = 1.0f;
|
||||||
|
float top_uv = 1.0f;
|
||||||
|
float bottom_uv = 0.0f;
|
||||||
|
|
||||||
|
float internal_left_uv = (float)m_background_texture.metadata.left * inv_tex_width;
|
||||||
|
float internal_right_uv = 1.0f - (float)m_background_texture.metadata.right * inv_tex_width;
|
||||||
|
float internal_top_uv = 1.0f - (float)m_background_texture.metadata.top * inv_tex_height;
|
||||||
|
float internal_bottom_uv = (float)m_background_texture.metadata.bottom * inv_tex_height;
|
||||||
|
|
||||||
|
// top-left corner
|
||||||
|
if ((m_layout.horizontal_orientation == Layout::HO_Left) || (m_layout.vertical_orientation == Layout::VO_Top))
|
||||||
|
GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
else
|
||||||
|
GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { left_uv, internal_top_uv }, { internal_left_uv, internal_top_uv }, { internal_left_uv, top_uv }, { left_uv, top_uv } });
|
||||||
|
|
||||||
|
// top edge
|
||||||
|
if (m_layout.vertical_orientation == Layout::VO_Top)
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
else
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_top, top, { { internal_left_uv, internal_top_uv }, { internal_right_uv, internal_top_uv }, { internal_right_uv, top_uv }, { internal_left_uv, top_uv } });
|
||||||
|
|
||||||
|
// top-right corner
|
||||||
|
if ((m_layout.horizontal_orientation == Layout::HO_Right) || (m_layout.vertical_orientation == Layout::VO_Top))
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
else
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_right_uv, internal_top_uv }, { right_uv, internal_top_uv }, { right_uv, top_uv }, { internal_right_uv, top_uv } });
|
||||||
|
|
||||||
|
// center-left edge
|
||||||
|
if (m_layout.horizontal_orientation == Layout::HO_Left)
|
||||||
|
GLTexture::render_sub_texture(tex_id, left, internal_left, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
else
|
||||||
|
GLTexture::render_sub_texture(tex_id, left, internal_left, internal_bottom, internal_top, { { left_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv }, { internal_left_uv, internal_top_uv }, { left_uv, internal_top_uv } });
|
||||||
|
|
||||||
|
// center
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
|
||||||
|
// center-right edge
|
||||||
|
if (m_layout.horizontal_orientation == Layout::HO_Right)
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_right, right, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
else
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_right, right, internal_bottom, internal_top, { { internal_right_uv, internal_bottom_uv }, { right_uv, internal_bottom_uv }, { right_uv, internal_top_uv }, { internal_right_uv, internal_top_uv } });
|
||||||
|
|
||||||
|
// bottom-left corner
|
||||||
|
if ((m_layout.horizontal_orientation == Layout::HO_Left) || (m_layout.vertical_orientation == Layout::VO_Bottom))
|
||||||
|
GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
else
|
||||||
|
GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { left_uv, bottom_uv }, { internal_left_uv, bottom_uv }, { internal_left_uv, internal_bottom_uv }, { left_uv, internal_bottom_uv } });
|
||||||
|
|
||||||
|
// bottom edge
|
||||||
|
if (m_layout.vertical_orientation == Layout::VO_Bottom)
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_left, internal_right, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
else
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_left, internal_right, bottom, internal_bottom, { { internal_left_uv, bottom_uv }, { internal_right_uv, bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv } });
|
||||||
|
|
||||||
|
// bottom-right corner
|
||||||
|
if ((m_layout.horizontal_orientation == Layout::HO_Right) || (m_layout.vertical_orientation == Layout::VO_Bottom))
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
else
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_right_uv, bottom_uv }, { right_uv, bottom_uv }, { right_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GLToolbar::render_horizontal(const GLCanvas3D& parent) const
|
void GLToolbar::render_horizontal(const GLCanvas3D& parent) const
|
||||||
{
|
{
|
||||||
unsigned int tex_id = m_icons_texture.get_id();
|
unsigned int tex_id = m_icons_texture.get_id();
|
||||||
|
@ -991,88 +1105,7 @@ void GLToolbar::render_horizontal(const GLCanvas3D& parent) const
|
||||||
float right = left + scaled_width;
|
float right = left + scaled_width;
|
||||||
float bottom = top - scaled_height;
|
float bottom = top - scaled_height;
|
||||||
|
|
||||||
// renders background
|
render_background(left, top, right, bottom, scaled_border);
|
||||||
unsigned int bg_tex_id = m_background_texture.texture.get_id();
|
|
||||||
float bg_tex_width = (float)m_background_texture.texture.get_width();
|
|
||||||
float bg_tex_height = (float)m_background_texture.texture.get_height();
|
|
||||||
if ((bg_tex_id != 0) && (bg_tex_width > 0) && (bg_tex_height > 0))
|
|
||||||
{
|
|
||||||
float inv_bg_tex_width = (bg_tex_width != 0.0f) ? 1.0f / bg_tex_width : 0.0f;
|
|
||||||
float inv_bg_tex_height = (bg_tex_height != 0.0f) ? 1.0f / bg_tex_height : 0.0f;
|
|
||||||
|
|
||||||
float bg_uv_left = 0.0f;
|
|
||||||
float bg_uv_right = 1.0f;
|
|
||||||
float bg_uv_top = 1.0f;
|
|
||||||
float bg_uv_bottom = 0.0f;
|
|
||||||
|
|
||||||
float bg_left = left;
|
|
||||||
float bg_right = right;
|
|
||||||
float bg_top = top;
|
|
||||||
float bg_bottom = bottom;
|
|
||||||
float bg_width = right - left;
|
|
||||||
float bg_height = top - bottom;
|
|
||||||
float bg_min_size = std::min(bg_width, bg_height);
|
|
||||||
|
|
||||||
float bg_uv_i_left = (float)m_background_texture.metadata.left * inv_bg_tex_width;
|
|
||||||
float bg_uv_i_right = 1.0f - (float)m_background_texture.metadata.right * inv_bg_tex_width;
|
|
||||||
float bg_uv_i_top = 1.0f - (float)m_background_texture.metadata.top * inv_bg_tex_height;
|
|
||||||
float bg_uv_i_bottom = (float)m_background_texture.metadata.bottom * inv_bg_tex_height;
|
|
||||||
|
|
||||||
float bg_i_left = bg_left + scaled_border;
|
|
||||||
float bg_i_right = bg_right - scaled_border;
|
|
||||||
float bg_i_top = bg_top - scaled_border;
|
|
||||||
float bg_i_bottom = bg_bottom + scaled_border;
|
|
||||||
|
|
||||||
switch (m_layout.orientation)
|
|
||||||
{
|
|
||||||
case Layout::Top:
|
|
||||||
{
|
|
||||||
bg_uv_top = bg_uv_i_top;
|
|
||||||
bg_i_top = bg_top;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Layout::Bottom:
|
|
||||||
{
|
|
||||||
bg_uv_bottom = bg_uv_i_bottom;
|
|
||||||
bg_i_bottom = bg_bottom;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Layout::Center:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if ((m_layout.border > 0) && (bg_uv_top != bg_uv_i_top))
|
|
||||||
{
|
|
||||||
if (bg_uv_left != bg_uv_i_left)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_top, bg_top, { { bg_uv_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_top }, { bg_uv_left, bg_uv_top } });
|
|
||||||
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_i_top, bg_top, { { bg_uv_i_left, bg_uv_i_top }, { bg_uv_i_right, bg_uv_i_top }, { bg_uv_i_right, bg_uv_top }, { bg_uv_i_left, bg_uv_top } });
|
|
||||||
|
|
||||||
if (bg_uv_right != bg_uv_i_right)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_top, bg_top, { { bg_uv_i_right, bg_uv_i_top }, { bg_uv_right, bg_uv_i_top }, { bg_uv_right, bg_uv_top }, { bg_uv_i_right, bg_uv_top } });
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_layout.border > 0) && (bg_uv_left != bg_uv_i_left))
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_bottom, bg_i_top, { { bg_uv_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_left, bg_uv_i_top } });
|
|
||||||
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_i_bottom, bg_i_top, { { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top } });
|
|
||||||
|
|
||||||
if ((m_layout.border > 0) && (bg_uv_right != bg_uv_i_right))
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_bottom, bg_i_top, { { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_top }, { bg_uv_i_right, bg_uv_i_top } });
|
|
||||||
|
|
||||||
if ((m_layout.border > 0) && (bg_uv_bottom != bg_uv_i_bottom))
|
|
||||||
{
|
|
||||||
if (bg_uv_left != bg_uv_i_left)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_bottom, bg_i_bottom, { { bg_uv_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_left, bg_uv_i_bottom } });
|
|
||||||
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_bottom, bg_i_bottom, { { bg_uv_i_left, bg_uv_bottom }, { bg_uv_i_right, bg_uv_bottom }, { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_bottom } });
|
|
||||||
|
|
||||||
if (bg_uv_right != bg_uv_i_right)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_bottom, bg_i_bottom, { { bg_uv_i_right, bg_uv_bottom }, { bg_uv_right, bg_uv_bottom }, { bg_uv_right, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_bottom } });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
left += scaled_border;
|
left += scaled_border;
|
||||||
top -= scaled_border;
|
top -= scaled_border;
|
||||||
|
@ -1121,88 +1154,7 @@ void GLToolbar::render_vertical(const GLCanvas3D& parent) const
|
||||||
float right = left + scaled_width;
|
float right = left + scaled_width;
|
||||||
float bottom = top - scaled_height;
|
float bottom = top - scaled_height;
|
||||||
|
|
||||||
// renders background
|
render_background(left, top, right, bottom, scaled_border);
|
||||||
unsigned int bg_tex_id = m_background_texture.texture.get_id();
|
|
||||||
float bg_tex_width = (float)m_background_texture.texture.get_width();
|
|
||||||
float bg_tex_height = (float)m_background_texture.texture.get_height();
|
|
||||||
if ((bg_tex_id != 0) && (bg_tex_width > 0) && (bg_tex_height > 0))
|
|
||||||
{
|
|
||||||
float inv_bg_tex_width = (bg_tex_width != 0.0f) ? 1.0f / bg_tex_width : 0.0f;
|
|
||||||
float inv_bg_tex_height = (bg_tex_height != 0.0f) ? 1.0f / bg_tex_height : 0.0f;
|
|
||||||
|
|
||||||
float bg_uv_left = 0.0f;
|
|
||||||
float bg_uv_right = 1.0f;
|
|
||||||
float bg_uv_top = 1.0f;
|
|
||||||
float bg_uv_bottom = 0.0f;
|
|
||||||
|
|
||||||
float bg_left = left;
|
|
||||||
float bg_right = right;
|
|
||||||
float bg_top = top;
|
|
||||||
float bg_bottom = bottom;
|
|
||||||
float bg_width = right - left;
|
|
||||||
float bg_height = top - bottom;
|
|
||||||
float bg_min_size = std::min(bg_width, bg_height);
|
|
||||||
|
|
||||||
float bg_uv_i_left = (float)m_background_texture.metadata.left * inv_bg_tex_width;
|
|
||||||
float bg_uv_i_right = 1.0f - (float)m_background_texture.metadata.right * inv_bg_tex_width;
|
|
||||||
float bg_uv_i_top = 1.0f - (float)m_background_texture.metadata.top * inv_bg_tex_height;
|
|
||||||
float bg_uv_i_bottom = (float)m_background_texture.metadata.bottom * inv_bg_tex_height;
|
|
||||||
|
|
||||||
float bg_i_left = bg_left + scaled_border;
|
|
||||||
float bg_i_right = bg_right - scaled_border;
|
|
||||||
float bg_i_top = bg_top - scaled_border;
|
|
||||||
float bg_i_bottom = bg_bottom + scaled_border;
|
|
||||||
|
|
||||||
switch (m_layout.orientation)
|
|
||||||
{
|
|
||||||
case Layout::Left:
|
|
||||||
{
|
|
||||||
bg_uv_left = bg_uv_i_left;
|
|
||||||
bg_i_left = bg_left;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Layout::Right:
|
|
||||||
{
|
|
||||||
bg_uv_right = bg_uv_i_right;
|
|
||||||
bg_i_right = bg_right;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Layout::Center:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if ((m_layout.border > 0) && (bg_uv_top != bg_uv_i_top))
|
|
||||||
{
|
|
||||||
if (bg_uv_left != bg_uv_i_left)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_top, bg_top, { { bg_uv_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_top }, { bg_uv_left, bg_uv_top } });
|
|
||||||
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_i_top, bg_top, { { bg_uv_i_left, bg_uv_i_top }, { bg_uv_i_right, bg_uv_i_top }, { bg_uv_i_right, bg_uv_top }, { bg_uv_i_left, bg_uv_top } });
|
|
||||||
|
|
||||||
if (bg_uv_right != bg_uv_i_right)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_top, bg_top, { { bg_uv_i_right, bg_uv_i_top }, { bg_uv_right, bg_uv_i_top }, { bg_uv_right, bg_uv_top }, { bg_uv_i_right, bg_uv_top } });
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_layout.border > 0) && (bg_uv_left != bg_uv_i_left))
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_bottom, bg_i_top, { { bg_uv_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_left, bg_uv_i_top } });
|
|
||||||
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_i_bottom, bg_i_top, { { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top } });
|
|
||||||
|
|
||||||
if ((m_layout.border > 0) && (bg_uv_right != bg_uv_i_right))
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_bottom, bg_i_top, { { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_top }, { bg_uv_i_right, bg_uv_i_top } });
|
|
||||||
|
|
||||||
if ((m_layout.border > 0) && (bg_uv_bottom != bg_uv_i_bottom))
|
|
||||||
{
|
|
||||||
if (bg_uv_left != bg_uv_i_left)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_bottom, bg_i_bottom, { { bg_uv_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_left, bg_uv_i_bottom } });
|
|
||||||
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_bottom, bg_i_bottom, { { bg_uv_i_left, bg_uv_bottom }, { bg_uv_i_right, bg_uv_bottom }, { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_bottom } });
|
|
||||||
|
|
||||||
if (bg_uv_right != bg_uv_i_right)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_bottom, bg_i_bottom, { { bg_uv_i_right, bg_uv_bottom }, { bg_uv_right, bg_uv_bottom }, { bg_uv_right, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_bottom } });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
left += scaled_border;
|
left += scaled_border;
|
||||||
top -= scaled_border;
|
top -= scaled_border;
|
||||||
|
|
|
@ -80,6 +80,7 @@ public:
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string icon_filename;
|
std::string icon_filename;
|
||||||
std::string tooltip;
|
std::string tooltip;
|
||||||
|
std::string additional_tooltip;
|
||||||
unsigned int sprite_id;
|
unsigned int sprite_id;
|
||||||
// mouse left click
|
// mouse left click
|
||||||
Option left;
|
Option left;
|
||||||
|
@ -112,6 +113,8 @@ public:
|
||||||
const std::string& get_name() const { return m_data.name; }
|
const std::string& get_name() const { return m_data.name; }
|
||||||
const std::string& get_icon_filename() const { return m_data.icon_filename; }
|
const std::string& get_icon_filename() const { return m_data.icon_filename; }
|
||||||
const std::string& get_tooltip() const { return m_data.tooltip; }
|
const std::string& get_tooltip() const { return m_data.tooltip; }
|
||||||
|
const std::string& get_additional_tooltip() const { return m_data.additional_tooltip; }
|
||||||
|
void set_additional_tooltip(const std::string& text) { m_data.additional_tooltip = text; }
|
||||||
|
|
||||||
void do_left_action() { m_last_action_type = Left; m_data.left.action_callback(); }
|
void do_left_action() { m_last_action_type = Left; m_data.left.action_callback(); }
|
||||||
void do_right_action() { m_last_action_type = Right; m_data.right.action_callback(); }
|
void do_right_action() { m_last_action_type = Right; m_data.right.action_callback(); }
|
||||||
|
@ -189,18 +192,25 @@ public:
|
||||||
Num_Types
|
Num_Types
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EOrientation : unsigned int
|
enum EHorizontalOrientation : unsigned char
|
||||||
{
|
{
|
||||||
Top,
|
HO_Left,
|
||||||
Bottom,
|
HO_Center,
|
||||||
Left,
|
HO_Right,
|
||||||
Right,
|
Num_Horizontal_Orientations
|
||||||
Center,
|
};
|
||||||
Num_Locations
|
|
||||||
|
enum EVerticalOrientation : unsigned char
|
||||||
|
{
|
||||||
|
VO_Top,
|
||||||
|
VO_Center,
|
||||||
|
VO_Bottom,
|
||||||
|
Num_Vertical_Orientations
|
||||||
};
|
};
|
||||||
|
|
||||||
EType type;
|
EType type;
|
||||||
EOrientation orientation;
|
EHorizontalOrientation horizontal_orientation;
|
||||||
|
EVerticalOrientation vertical_orientation;
|
||||||
float top;
|
float top;
|
||||||
float left;
|
float left;
|
||||||
float border;
|
float border;
|
||||||
|
@ -254,8 +264,10 @@ public:
|
||||||
|
|
||||||
Layout::EType get_layout_type() const;
|
Layout::EType get_layout_type() const;
|
||||||
void set_layout_type(Layout::EType type);
|
void set_layout_type(Layout::EType type);
|
||||||
Layout::EOrientation get_layout_orientation() const;
|
Layout::EHorizontalOrientation get_horizontal_orientation() const { return m_layout.horizontal_orientation; }
|
||||||
void set_layout_orientation(Layout::EOrientation orientation);
|
void set_horizontal_orientation(Layout::EHorizontalOrientation orientation) { m_layout.horizontal_orientation = orientation; }
|
||||||
|
Layout::EVerticalOrientation get_vertical_orientation() const { return m_layout.vertical_orientation; }
|
||||||
|
void set_vertical_orientation(Layout::EVerticalOrientation orientation) { m_layout.vertical_orientation = orientation; }
|
||||||
|
|
||||||
void set_position(float top, float left);
|
void set_position(float top, float left);
|
||||||
void set_border(float border);
|
void set_border(float border);
|
||||||
|
@ -288,6 +300,9 @@ public:
|
||||||
|
|
||||||
const std::string& get_tooltip() const { return m_tooltip; }
|
const std::string& get_tooltip() const { return m_tooltip; }
|
||||||
|
|
||||||
|
void get_additional_tooltip(unsigned int item_id, std::string& text);
|
||||||
|
void set_additional_tooltip(unsigned int item_id, const std::string& text);
|
||||||
|
|
||||||
// returns true if any item changed its state
|
// returns true if any item changed its state
|
||||||
bool update_items_state();
|
bool update_items_state();
|
||||||
|
|
||||||
|
@ -311,6 +326,7 @@ private:
|
||||||
int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
|
int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
|
||||||
int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
|
int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
|
||||||
|
|
||||||
|
void render_background(float left, float top, float right, float bottom, float border) const;
|
||||||
void render_horizontal(const GLCanvas3D& parent) const;
|
void render_horizontal(const GLCanvas3D& parent) const;
|
||||||
void render_vertical(const GLCanvas3D& parent) const;
|
void render_vertical(const GLCanvas3D& parent) const;
|
||||||
|
|
||||||
|
|
|
@ -199,18 +199,17 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||||
m_mirror_bitmap_off = ScalableBitmap(parent, "mirroring_off.png");
|
m_mirror_bitmap_off = ScalableBitmap(parent, "mirroring_off.png");
|
||||||
m_mirror_bitmap_hidden = ScalableBitmap(parent, "mirroring_transparent.png");
|
m_mirror_bitmap_hidden = ScalableBitmap(parent, "mirroring_transparent.png");
|
||||||
|
|
||||||
for (const std::string axis : { "x", "y", "z" }) {
|
static const char axes[] = { 'X', 'Y', 'Z' };
|
||||||
const std::string label = boost::algorithm::to_upper_copy(axis);
|
for (size_t axis_idx = 0; axis_idx < sizeof(axes); axis_idx++) {
|
||||||
def.set_default_value(new ConfigOptionString{ " " + label });
|
const char label = axes[axis_idx];
|
||||||
Option option = Option(def, axis + "_axis_legend");
|
def.set_default_value(new ConfigOptionString{ std::string(" ") + label });
|
||||||
|
Option option(def, std::string() + label + "_axis_legend");
|
||||||
unsigned int axis_idx = (axis[0] - 'x'); // 0, 1 or 2
|
|
||||||
|
|
||||||
// We will add a button to toggle mirroring to each axis:
|
// We will add a button to toggle mirroring to each axis:
|
||||||
auto mirror_button = [this, mirror_btn_width, axis_idx, &label](wxWindow* parent) {
|
auto mirror_button = [this, mirror_btn_width, axis_idx, label](wxWindow* parent) {
|
||||||
wxSize btn_size(em_unit(parent) * mirror_btn_width, em_unit(parent) * mirror_btn_width);
|
wxSize btn_size(em_unit(parent) * mirror_btn_width, em_unit(parent) * mirror_btn_width);
|
||||||
auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_off.png", wxEmptyString, btn_size, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW);
|
auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_off.png", wxEmptyString, btn_size, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW);
|
||||||
btn->SetToolTip(wxString::Format(_(L("Toggle %s axis mirroring")), label));
|
btn->SetToolTip(wxString::Format(_(L("Toggle %c axis mirroring")), (int)label));
|
||||||
|
|
||||||
m_mirror_buttons[axis_idx].first = btn;
|
m_mirror_buttons[axis_idx].first = btn;
|
||||||
m_mirror_buttons[axis_idx].second = mbShown;
|
m_mirror_buttons[axis_idx].second = mbShown;
|
||||||
|
@ -245,7 +244,8 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||||
canvas->do_mirror(L("Set Mirror"));
|
canvas->do_mirror(L("Set Mirror"));
|
||||||
UpdateAndShow(true);
|
UpdateAndShow(true);
|
||||||
});
|
});
|
||||||
return sizer;
|
|
||||||
|
return sizer;
|
||||||
};
|
};
|
||||||
|
|
||||||
option.side_widget = mirror_button;
|
option.side_widget = mirror_button;
|
||||||
|
|
|
@ -63,7 +63,8 @@ bool View3D::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_
|
||||||
m_canvas->set_config(config);
|
m_canvas->set_config(config);
|
||||||
m_canvas->enable_gizmos(true);
|
m_canvas->enable_gizmos(true);
|
||||||
m_canvas->enable_selection(true);
|
m_canvas->enable_selection(true);
|
||||||
m_canvas->enable_toolbar(true);
|
m_canvas->enable_main_toolbar(true);
|
||||||
|
m_canvas->enable_undoredo_toolbar(true);
|
||||||
|
|
||||||
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
|
main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
|
||||||
|
|
|
@ -879,6 +879,60 @@ void GLGizmosManager::reset()
|
||||||
m_gizmos.clear();
|
m_gizmos.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmosManager::render_background(float left, float top, float right, float bottom, float border) const
|
||||||
|
{
|
||||||
|
unsigned int tex_id = m_background_texture.texture.get_id();
|
||||||
|
float tex_width = (float)m_background_texture.texture.get_width();
|
||||||
|
float tex_height = (float)m_background_texture.texture.get_height();
|
||||||
|
if ((tex_id != 0) && (tex_width > 0) && (tex_height > 0))
|
||||||
|
{
|
||||||
|
float inv_tex_width = (tex_width != 0.0f) ? 1.0f / tex_width : 0.0f;
|
||||||
|
float inv_tex_height = (tex_height != 0.0f) ? 1.0f / tex_height : 0.0f;
|
||||||
|
|
||||||
|
float internal_left = left + border;
|
||||||
|
float internal_right = right - border;
|
||||||
|
float internal_top = top - border;
|
||||||
|
float internal_bottom = bottom + border;
|
||||||
|
|
||||||
|
float left_uv = 0.0f;
|
||||||
|
float right_uv = 1.0f;
|
||||||
|
float top_uv = 1.0f;
|
||||||
|
float bottom_uv = 0.0f;
|
||||||
|
|
||||||
|
float internal_left_uv = (float)m_background_texture.metadata.left * inv_tex_width;
|
||||||
|
float internal_right_uv = 1.0f - (float)m_background_texture.metadata.right * inv_tex_width;
|
||||||
|
float internal_top_uv = 1.0f - (float)m_background_texture.metadata.top * inv_tex_height;
|
||||||
|
float internal_bottom_uv = (float)m_background_texture.metadata.bottom * inv_tex_height;
|
||||||
|
|
||||||
|
// top-left corner
|
||||||
|
GLTexture::render_sub_texture(tex_id, left, internal_left, internal_top, top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
|
||||||
|
// top edge
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_top, top, { { internal_left_uv, internal_top_uv }, { internal_right_uv, internal_top_uv }, { internal_right_uv, top_uv }, { internal_left_uv, top_uv } });
|
||||||
|
|
||||||
|
// top-right corner
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_right, right, internal_top, top, { { internal_right_uv, internal_top_uv }, { right_uv, internal_top_uv }, { right_uv, top_uv }, { internal_right_uv, top_uv } });
|
||||||
|
|
||||||
|
// center-left edge
|
||||||
|
GLTexture::render_sub_texture(tex_id, left, internal_left, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
|
||||||
|
// center
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_left, internal_right, internal_bottom, internal_top, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
|
||||||
|
// center-right edge
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_right, right, internal_bottom, internal_top, { { internal_right_uv, internal_bottom_uv }, { right_uv, internal_bottom_uv }, { right_uv, internal_top_uv }, { internal_right_uv, internal_top_uv } });
|
||||||
|
|
||||||
|
// bottom-left corner
|
||||||
|
GLTexture::render_sub_texture(tex_id, left, internal_left, bottom, internal_bottom, { { internal_left_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_right_uv, internal_top_uv }, { internal_left_uv, internal_top_uv } });
|
||||||
|
|
||||||
|
// bottom edge
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_left, internal_right, bottom, internal_bottom, { { internal_left_uv, bottom_uv }, { internal_right_uv, bottom_uv }, { internal_right_uv, internal_bottom_uv }, { internal_left_uv, internal_bottom_uv } });
|
||||||
|
|
||||||
|
// bottom-right corner
|
||||||
|
GLTexture::render_sub_texture(tex_id, internal_right, right, bottom, internal_bottom, { { internal_right_uv, bottom_uv }, { right_uv, bottom_uv }, { right_uv, internal_bottom_uv }, { internal_right_uv, internal_bottom_uv } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GLGizmosManager::do_render_overlay() const
|
void GLGizmosManager::do_render_overlay() const
|
||||||
{
|
{
|
||||||
if (m_gizmos.empty())
|
if (m_gizmos.empty())
|
||||||
|
@ -901,71 +955,7 @@ void GLGizmosManager::do_render_overlay() const
|
||||||
float right = left + width * inv_zoom;
|
float right = left + width * inv_zoom;
|
||||||
float bottom = top - height * inv_zoom;
|
float bottom = top - height * inv_zoom;
|
||||||
|
|
||||||
// renders background
|
render_background(left, top, right, bottom, scaled_border);
|
||||||
unsigned int bg_tex_id = m_background_texture.texture.get_id();
|
|
||||||
float bg_tex_width = (float)m_background_texture.texture.get_width();
|
|
||||||
float bg_tex_height = (float)m_background_texture.texture.get_height();
|
|
||||||
if ((bg_tex_id != 0) && (bg_tex_width > 0) && (bg_tex_height > 0))
|
|
||||||
{
|
|
||||||
float inv_bg_tex_width = (bg_tex_width != 0.0f) ? 1.0f / bg_tex_width : 0.0f;
|
|
||||||
float inv_bg_tex_height = (bg_tex_height != 0.0f) ? 1.0f / bg_tex_height : 0.0f;
|
|
||||||
|
|
||||||
float bg_uv_left = 0.0f;
|
|
||||||
float bg_uv_right = 1.0f;
|
|
||||||
float bg_uv_top = 1.0f;
|
|
||||||
float bg_uv_bottom = 0.0f;
|
|
||||||
|
|
||||||
float bg_left = left;
|
|
||||||
float bg_right = right;
|
|
||||||
float bg_top = top;
|
|
||||||
float bg_bottom = bottom;
|
|
||||||
float bg_width = right - left;
|
|
||||||
float bg_height = top - bottom;
|
|
||||||
float bg_min_size = std::min(bg_width, bg_height);
|
|
||||||
|
|
||||||
float bg_uv_i_left = (float)m_background_texture.metadata.left * inv_bg_tex_width;
|
|
||||||
float bg_uv_i_right = 1.0f - (float)m_background_texture.metadata.right * inv_bg_tex_width;
|
|
||||||
float bg_uv_i_top = 1.0f - (float)m_background_texture.metadata.top * inv_bg_tex_height;
|
|
||||||
float bg_uv_i_bottom = (float)m_background_texture.metadata.bottom * inv_bg_tex_height;
|
|
||||||
|
|
||||||
float bg_i_left = bg_left + scaled_border;
|
|
||||||
float bg_i_right = bg_right - scaled_border;
|
|
||||||
float bg_i_top = bg_top - scaled_border;
|
|
||||||
float bg_i_bottom = bg_bottom + scaled_border;
|
|
||||||
|
|
||||||
bg_uv_left = bg_uv_i_left;
|
|
||||||
bg_i_left = bg_left;
|
|
||||||
|
|
||||||
if ((m_overlay_border > 0) && (bg_uv_top != bg_uv_i_top))
|
|
||||||
{
|
|
||||||
if (bg_uv_left != bg_uv_i_left)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_top, bg_top, { { bg_uv_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_top }, { bg_uv_left, bg_uv_top } });
|
|
||||||
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_i_top, bg_top, { { bg_uv_i_left, bg_uv_i_top }, { bg_uv_i_right, bg_uv_i_top }, { bg_uv_i_right, bg_uv_top }, { bg_uv_i_left, bg_uv_top } });
|
|
||||||
|
|
||||||
if (bg_uv_right != bg_uv_i_right)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_top, bg_top, { { bg_uv_i_right, bg_uv_i_top }, { bg_uv_right, bg_uv_i_top }, { bg_uv_right, bg_uv_top }, { bg_uv_i_right, bg_uv_top } });
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_overlay_border > 0) && (bg_uv_left != bg_uv_i_left))
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_bottom, bg_i_top, { { bg_uv_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_left, bg_uv_i_top } });
|
|
||||||
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_i_bottom, bg_i_top, { { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top } });
|
|
||||||
|
|
||||||
if ((m_overlay_border > 0) && (bg_uv_right != bg_uv_i_right))
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_bottom, bg_i_top, { { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_top }, { bg_uv_i_right, bg_uv_i_top } });
|
|
||||||
|
|
||||||
if ((m_overlay_border > 0) && (bg_uv_bottom != bg_uv_i_bottom))
|
|
||||||
{
|
|
||||||
if (bg_uv_left != bg_uv_i_left)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_bottom, bg_i_bottom, { { bg_uv_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_left, bg_uv_i_bottom } });
|
|
||||||
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_bottom, bg_i_bottom, { { bg_uv_i_left, bg_uv_bottom }, { bg_uv_i_right, bg_uv_bottom }, { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_bottom } });
|
|
||||||
|
|
||||||
if (bg_uv_right != bg_uv_i_right)
|
|
||||||
GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_bottom, bg_i_bottom, { { bg_uv_i_right, bg_uv_bottom }, { bg_uv_right, bg_uv_bottom }, { bg_uv_right, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_bottom } });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
top_x += scaled_border;
|
top_x += scaled_border;
|
||||||
top_y -= scaled_border;
|
top_y -= scaled_border;
|
||||||
|
|
|
@ -187,6 +187,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
void render_background(float left, float top, float right, float bottom, float border) const;
|
||||||
void do_render_overlay() const;
|
void do_render_overlay() const;
|
||||||
|
|
||||||
float get_total_overlay_height() const;
|
float get_total_overlay_height() const;
|
||||||
|
|
|
@ -3430,7 +3430,8 @@ void Plater::priv::init_view_toolbar()
|
||||||
if (!view_toolbar.init(background_data))
|
if (!view_toolbar.init(background_data))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
view_toolbar.set_layout_orientation(GLToolbar::Layout::Bottom);
|
view_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Left);
|
||||||
|
view_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Bottom);
|
||||||
view_toolbar.set_border(5.0f);
|
view_toolbar.set_border(5.0f);
|
||||||
view_toolbar.set_gap_size(1.0f);
|
view_toolbar.set_gap_size(1.0f);
|
||||||
|
|
||||||
|
@ -3594,6 +3595,13 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name)
|
||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
if (this->view3D->is_layers_editing_enabled())
|
if (this->view3D->is_layers_editing_enabled())
|
||||||
flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE;
|
flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE;
|
||||||
|
//FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config.
|
||||||
|
// This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
|
||||||
|
if (this->printer_technology == ptFFF) {
|
||||||
|
const DynamicPrintConfig &config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
|
model.wipe_tower.position = Vec2d(config.opt_float("wipe_tower_x"), config.opt_float("wipe_tower_y"));
|
||||||
|
model.wipe_tower.rotation = config.opt_float("wipe_tower_rotation_angle");
|
||||||
|
}
|
||||||
this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology, flags);
|
this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology, flags);
|
||||||
this->undo_redo_stack.release_least_recently_used();
|
this->undo_redo_stack.release_least_recently_used();
|
||||||
// Save the last active preset name of a particular printer technology.
|
// Save the last active preset name of a particular printer technology.
|
||||||
|
@ -3640,6 +3648,13 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
|
||||||
}
|
}
|
||||||
// Save the last active preset name of a particular printer technology.
|
// Save the last active preset name of a particular printer technology.
|
||||||
((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name();
|
((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name();
|
||||||
|
//FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config.
|
||||||
|
// This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
|
||||||
|
if (this->printer_technology == ptFFF) {
|
||||||
|
const DynamicPrintConfig &config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
|
model.wipe_tower.position = Vec2d(config.opt_float("wipe_tower_x"), config.opt_float("wipe_tower_y"));
|
||||||
|
model.wipe_tower.rotation = config.opt_float("wipe_tower_rotation_angle");
|
||||||
|
}
|
||||||
// Flags made of Snapshot::Flags enum values.
|
// Flags made of Snapshot::Flags enum values.
|
||||||
unsigned int new_flags = it_snapshot->flags;
|
unsigned int new_flags = it_snapshot->flags;
|
||||||
unsigned int top_snapshot_flags = 0;
|
unsigned int top_snapshot_flags = 0;
|
||||||
|
@ -3647,8 +3662,8 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
|
||||||
top_snapshot_flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE;
|
top_snapshot_flags |= UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE;
|
||||||
bool new_variable_layer_editing_active = (new_flags & UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE) != 0;
|
bool new_variable_layer_editing_active = (new_flags & UndoRedo::Snapshot::VARIABLE_LAYER_EDITING_ACTIVE) != 0;
|
||||||
// Disable layer editing before the Undo / Redo jump.
|
// Disable layer editing before the Undo / Redo jump.
|
||||||
if (! new_variable_layer_editing_active && view3D->is_layers_editing_enabled())
|
if (!new_variable_layer_editing_active && view3D->is_layers_editing_enabled())
|
||||||
view3D->enable_layers_editing(false);
|
view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting"));
|
||||||
// Do the jump in time.
|
// Do the jump in time.
|
||||||
if (it_snapshot->timestamp < this->undo_redo_stack.active_snapshot_time() ?
|
if (it_snapshot->timestamp < this->undo_redo_stack.active_snapshot_time() ?
|
||||||
this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology, top_snapshot_flags, it_snapshot->timestamp) :
|
this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), this->printer_technology, top_snapshot_flags, it_snapshot->timestamp) :
|
||||||
|
@ -3662,11 +3677,27 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
|
||||||
// This also switches the printer technology based on the printer technology of the active printer profile.
|
// This also switches the printer technology based on the printer technology of the active printer profile.
|
||||||
wxGetApp().load_current_presets();
|
wxGetApp().load_current_presets();
|
||||||
}
|
}
|
||||||
this->update_after_undo_redo(temp_snapshot_was_taken);
|
//FIXME updating the Print config from the Wipe tower config values at the ModelWipeTower.
|
||||||
|
// This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
|
||||||
|
if (this->printer_technology == ptFFF) {
|
||||||
|
const DynamicPrintConfig ¤t_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
|
Vec2d current_position(current_config.opt_float("wipe_tower_x"), current_config.opt_float("wipe_tower_y"));
|
||||||
|
double current_rotation = current_config.opt_float("wipe_tower_rotation_angle");
|
||||||
|
if (current_position != model.wipe_tower.position || current_rotation != model.wipe_tower.rotation) {
|
||||||
|
DynamicPrintConfig new_config;
|
||||||
|
new_config.set_key_value("wipe_tower_x", new ConfigOptionFloat(model.wipe_tower.position.x()));
|
||||||
|
new_config.set_key_value("wipe_tower_y", new ConfigOptionFloat(model.wipe_tower.position.y()));
|
||||||
|
new_config.set_key_value("wipe_tower_rotation_angle", new ConfigOptionFloat(model.wipe_tower.rotation));
|
||||||
|
Tab *tab_print = wxGetApp().get_tab(Preset::TYPE_PRINT);
|
||||||
|
tab_print->load_config(new_config);
|
||||||
|
tab_print->update_dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->update_after_undo_redo(temp_snapshot_was_taken);
|
||||||
// Enable layer editing after the Undo / Redo jump.
|
// Enable layer editing after the Undo / Redo jump.
|
||||||
if (! view3D->is_layers_editing_enabled() && this->layers_height_allowed() && new_variable_layer_editing_active)
|
if (! view3D->is_layers_editing_enabled() && this->layers_height_allowed() && new_variable_layer_editing_active)
|
||||||
view3D->enable_layers_editing(true);
|
view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */)
|
void Plater::priv::update_after_undo_redo(bool /* temp_snapshot_was_taken */)
|
||||||
|
@ -4278,6 +4309,19 @@ bool Plater::undo_redo_string_getter(const bool is_undo, int idx, const char** o
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::undo_redo_topmost_string_getter(const bool is_undo, std::string& out_text)
|
||||||
|
{
|
||||||
|
const std::vector<UndoRedo::Snapshot>& ss_stack = p->undo_redo_stack.snapshots();
|
||||||
|
const int idx_in_ss_stack = p->get_active_snapshot_index() + (is_undo ? -1 : 0);
|
||||||
|
|
||||||
|
if (0 < idx_in_ss_stack && idx_in_ss_stack < ss_stack.size() - 1) {
|
||||||
|
out_text = ss_stack[idx_in_ss_stack].name;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_text = L("");
|
||||||
|
}
|
||||||
|
|
||||||
void Plater::on_extruders_change(int num_extruders)
|
void Plater::on_extruders_change(int num_extruders)
|
||||||
{
|
{
|
||||||
auto& choices = sidebar().combos_filament();
|
auto& choices = sidebar().combos_filament();
|
||||||
|
|
|
@ -196,6 +196,7 @@ public:
|
||||||
void undo_to(int selection);
|
void undo_to(int selection);
|
||||||
void redo_to(int selection);
|
void redo_to(int selection);
|
||||||
bool undo_redo_string_getter(const bool is_undo, int idx, const char** out_text);
|
bool undo_redo_string_getter(const bool is_undo, int idx, const char** out_text);
|
||||||
|
void undo_redo_topmost_string_getter(const bool is_undo, std::string& out_text);
|
||||||
const Slic3r::UndoRedo::Stack& undo_redo_stack() const;
|
const Slic3r::UndoRedo::Stack& undo_redo_stack() const;
|
||||||
|
|
||||||
void on_extruders_change(int extruders_count);
|
void on_extruders_change(int extruders_count);
|
||||||
|
|
|
@ -514,11 +514,11 @@ public:
|
||||||
const Selection& selection_deserialized() const { return m_selection; }
|
const Selection& selection_deserialized() const { return m_selection; }
|
||||||
|
|
||||||
//protected:
|
//protected:
|
||||||
template<typename T, typename T_AS> ObjectID save_mutable_object(const T &object);
|
template<typename T> ObjectID save_mutable_object(const T &object);
|
||||||
template<typename T> ObjectID save_immutable_object(std::shared_ptr<const T> &object, bool optional);
|
template<typename T> ObjectID save_immutable_object(std::shared_ptr<const T> &object, bool optional);
|
||||||
template<typename T> T* load_mutable_object(const Slic3r::ObjectID id);
|
template<typename T> T* load_mutable_object(const Slic3r::ObjectID id);
|
||||||
template<typename T> std::shared_ptr<const T> load_immutable_object(const Slic3r::ObjectID id, bool optional);
|
template<typename T> std::shared_ptr<const T> load_immutable_object(const Slic3r::ObjectID id, bool optional);
|
||||||
template<typename T, typename T_AS> void load_mutable_object(const Slic3r::ObjectID id, T &target);
|
template<typename T> void load_mutable_object(const Slic3r::ObjectID id, T &target);
|
||||||
|
|
||||||
#ifdef SLIC3R_UNDOREDO_DEBUG
|
#ifdef SLIC3R_UNDOREDO_DEBUG
|
||||||
std::string format() const {
|
std::string format() const {
|
||||||
|
@ -601,7 +601,6 @@ class ModelObject;
|
||||||
class ModelVolume;
|
class ModelVolume;
|
||||||
class ModelInstance;
|
class ModelInstance;
|
||||||
class ModelMaterial;
|
class ModelMaterial;
|
||||||
class ModelConfig;
|
|
||||||
class DynamicPrintConfig;
|
class DynamicPrintConfig;
|
||||||
class TriangleMesh;
|
class TriangleMesh;
|
||||||
|
|
||||||
|
@ -616,14 +615,13 @@ namespace cereal
|
||||||
template <class Archive> struct specialize<Archive, Slic3r::ModelVolume*, cereal::specialization::non_member_load_save> {};
|
template <class Archive> struct specialize<Archive, Slic3r::ModelVolume*, cereal::specialization::non_member_load_save> {};
|
||||||
template <class Archive> struct specialize<Archive, Slic3r::ModelInstance*, cereal::specialization::non_member_load_save> {};
|
template <class Archive> struct specialize<Archive, Slic3r::ModelInstance*, cereal::specialization::non_member_load_save> {};
|
||||||
template <class Archive> struct specialize<Archive, Slic3r::ModelMaterial*, cereal::specialization::non_member_load_save> {};
|
template <class Archive> struct specialize<Archive, Slic3r::ModelMaterial*, cereal::specialization::non_member_load_save> {};
|
||||||
template <class Archive> struct specialize<Archive, Slic3r::ModelConfig, cereal::specialization::non_member_load_save> {};
|
|
||||||
template <class Archive> struct specialize<Archive, std::shared_ptr<Slic3r::TriangleMesh>, cereal::specialization::non_member_load_save> {};
|
template <class Archive> struct specialize<Archive, std::shared_ptr<Slic3r::TriangleMesh>, cereal::specialization::non_member_load_save> {};
|
||||||
|
|
||||||
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
||||||
// store just the ObjectID to this stream.
|
// store just the ObjectID to this stream.
|
||||||
template <class T> void save(BinaryOutputArchive& ar, T* const& ptr)
|
template <class T> void save(BinaryOutputArchive& ar, T* const& ptr)
|
||||||
{
|
{
|
||||||
ar(cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar).save_mutable_object<T, T>(*ptr));
|
ar(cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar).save_mutable_object<T>(*ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load ObjectBase derived class from the Undo / Redo stack as a separate object
|
// Load ObjectBase derived class from the Undo / Redo stack as a separate object
|
||||||
|
@ -655,19 +653,18 @@ namespace cereal
|
||||||
|
|
||||||
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
||||||
// store just the ObjectID to this stream.
|
// store just the ObjectID to this stream.
|
||||||
void save(BinaryOutputArchive& ar, const Slic3r::ModelConfig &cfg)
|
template<class T> void save_by_value(BinaryOutputArchive& ar, const T &cfg)
|
||||||
{
|
{
|
||||||
ar(cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar).save_mutable_object<Slic3r::ModelConfig, Slic3r::DynamicPrintConfig>(cfg));
|
ar(cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar).save_mutable_object<T>(cfg));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load ObjectBase derived class from the Undo / Redo stack as a separate object
|
// Load ObjectBase derived class from the Undo / Redo stack as a separate object
|
||||||
// based on the ObjectID loaded from this stream.
|
// based on the ObjectID loaded from this stream.
|
||||||
void load(BinaryInputArchive& ar, Slic3r::ModelConfig &cfg)
|
template<class T> void load_by_value(BinaryInputArchive& ar, T &cfg)
|
||||||
{
|
{
|
||||||
Slic3r::UndoRedo::StackImpl& stack = cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar);
|
Slic3r::UndoRedo::StackImpl& stack = cereal::get_user_data<Slic3r::UndoRedo::StackImpl>(ar);
|
||||||
size_t id;
|
size_t id;
|
||||||
ar(id);
|
ar(id);
|
||||||
stack.load_mutable_object<Slic3r::ModelConfig, Slic3r::DynamicPrintConfig>(Slic3r::ObjectID(id), cfg);
|
stack.load_mutable_object<T>(Slic3r::ObjectID(id), cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
// Store ObjectBase derived class onto the Undo / Redo stack as a separate object,
|
||||||
|
@ -723,7 +720,7 @@ template<typename T> std::shared_ptr<const T>& ImmutableObjectHistory<T>::share
|
||||||
return m_shared_object;
|
return m_shared_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename T_AS> ObjectID StackImpl::save_mutable_object(const T &object)
|
template<typename T> ObjectID StackImpl::save_mutable_object(const T &object)
|
||||||
{
|
{
|
||||||
// First find or allocate a history stack for the ObjectID of this object instance.
|
// First find or allocate a history stack for the ObjectID of this object instance.
|
||||||
auto it_object_history = m_objects.find(object.id());
|
auto it_object_history = m_objects.find(object.id());
|
||||||
|
@ -734,7 +731,7 @@ template<typename T, typename T_AS> ObjectID StackImpl::save_mutable_object(cons
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
{
|
{
|
||||||
Slic3r::UndoRedo::OutputArchive archive(*this, oss);
|
Slic3r::UndoRedo::OutputArchive archive(*this, oss);
|
||||||
archive(static_cast<const T_AS&>(object));
|
archive(object);
|
||||||
}
|
}
|
||||||
object_history->save(m_active_snapshot_time, m_current_time, oss.str());
|
object_history->save(m_active_snapshot_time, m_current_time, oss.str());
|
||||||
return object.id();
|
return object.id();
|
||||||
|
@ -758,7 +755,7 @@ template<typename T> ObjectID StackImpl::save_immutable_object(std::shared_ptr<c
|
||||||
template<typename T> T* StackImpl::load_mutable_object(const Slic3r::ObjectID id)
|
template<typename T> T* StackImpl::load_mutable_object(const Slic3r::ObjectID id)
|
||||||
{
|
{
|
||||||
T *target = new T();
|
T *target = new T();
|
||||||
this->load_mutable_object<T, T>(id, *target);
|
this->load_mutable_object<T>(id, *target);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -775,7 +772,7 @@ template<typename T> std::shared_ptr<const T> StackImpl::load_immutable_object(c
|
||||||
return object_history->shared_ptr(*this);
|
return object_history->shared_ptr(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename T_AS> void StackImpl::load_mutable_object(const Slic3r::ObjectID id, T &target)
|
template<typename T> void StackImpl::load_mutable_object(const Slic3r::ObjectID id, T &target)
|
||||||
{
|
{
|
||||||
// First find a history stack for the ObjectID of this object instance.
|
// First find a history stack for the ObjectID of this object instance.
|
||||||
auto it_object_history = m_objects.find(id);
|
auto it_object_history = m_objects.find(id);
|
||||||
|
@ -785,7 +782,7 @@ template<typename T, typename T_AS> void StackImpl::load_mutable_object(const Sl
|
||||||
std::istringstream iss(object_history->load(m_active_snapshot_time));
|
std::istringstream iss(object_history->load(m_active_snapshot_time));
|
||||||
Slic3r::UndoRedo::InputArchive archive(*this, iss);
|
Slic3r::UndoRedo::InputArchive archive(*this, iss);
|
||||||
target.m_id = id;
|
target.m_id = id;
|
||||||
archive(static_cast<T_AS&>(target));
|
archive(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
|
// Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
|
||||||
|
@ -800,14 +797,14 @@ void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Mo
|
||||||
m_snapshots.erase(it, m_snapshots.end());
|
m_snapshots.erase(it, m_snapshots.end());
|
||||||
}
|
}
|
||||||
// Take new snapshots.
|
// Take new snapshots.
|
||||||
this->save_mutable_object<Slic3r::Model, Slic3r::Model>(model);
|
this->save_mutable_object<Slic3r::Model>(model);
|
||||||
m_selection.volumes_and_instances.clear();
|
m_selection.volumes_and_instances.clear();
|
||||||
m_selection.volumes_and_instances.reserve(selection.get_volume_idxs().size());
|
m_selection.volumes_and_instances.reserve(selection.get_volume_idxs().size());
|
||||||
m_selection.mode = selection.get_mode();
|
m_selection.mode = selection.get_mode();
|
||||||
for (unsigned int volume_idx : selection.get_volume_idxs())
|
for (unsigned int volume_idx : selection.get_volume_idxs())
|
||||||
m_selection.volumes_and_instances.emplace_back(selection.get_volume(volume_idx)->geometry_id);
|
m_selection.volumes_and_instances.emplace_back(selection.get_volume(volume_idx)->geometry_id);
|
||||||
this->save_mutable_object<Selection, Selection>(m_selection);
|
this->save_mutable_object<Selection>(m_selection);
|
||||||
this->save_mutable_object<Slic3r::GUI::GLGizmosManager, Slic3r::GUI::GLGizmosManager>(gizmos);
|
this->save_mutable_object<Slic3r::GUI::GLGizmosManager>(gizmos);
|
||||||
// Save the snapshot info.
|
// Save the snapshot info.
|
||||||
m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id, printer_technology, flags);
|
m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id, printer_technology, flags);
|
||||||
m_active_snapshot_time = m_current_time;
|
m_active_snapshot_time = m_current_time;
|
||||||
|
@ -833,12 +830,12 @@ void StackImpl::load_snapshot(size_t timestamp, Slic3r::Model& model, Slic3r::GU
|
||||||
m_active_snapshot_time = timestamp;
|
m_active_snapshot_time = timestamp;
|
||||||
model.clear_objects();
|
model.clear_objects();
|
||||||
model.clear_materials();
|
model.clear_materials();
|
||||||
this->load_mutable_object<Slic3r::Model, Slic3r::Model>(ObjectID(it_snapshot->model_id), model);
|
this->load_mutable_object<Slic3r::Model>(ObjectID(it_snapshot->model_id), model);
|
||||||
model.update_links_bottom_up_recursive();
|
model.update_links_bottom_up_recursive();
|
||||||
m_selection.volumes_and_instances.clear();
|
m_selection.volumes_and_instances.clear();
|
||||||
this->load_mutable_object<Selection, Selection>(m_selection.id(), m_selection);
|
this->load_mutable_object<Selection>(m_selection.id(), m_selection);
|
||||||
gizmos.reset_all_states();
|
gizmos.reset_all_states();
|
||||||
this->load_mutable_object<Slic3r::GUI::GLGizmosManager, Slic3r::GUI::GLGizmosManager>(gizmos.id(), gizmos);
|
this->load_mutable_object<Slic3r::GUI::GLGizmosManager>(gizmos.id(), gizmos);
|
||||||
// Sort the volumes so that we may use binary search.
|
// Sort the volumes so that we may use binary search.
|
||||||
std::sort(m_selection.volumes_and_instances.begin(), m_selection.volumes_and_instances.end());
|
std::sort(m_selection.volumes_and_instances.begin(), m_selection.volumes_and_instances.end());
|
||||||
this->m_active_snapshot_time = timestamp;
|
this->m_active_snapshot_time = timestamp;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue