mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-04 06:11:02 +00:00
The G-code preview draws every toolpath segment as an instanced box, and its frame cost is linear in the number of segments drawn. On a plate of large objects that is enough that dragging the camera or a preview slider cannot keep up, and no amount of per-segment work changes that; only drawing fewer segments does. The objects themselves are cheaper: a mesh costs its triangles once, however many layers it has, and the preview already loads the objects as shells for its translucent ghost. A new preference, "Only render solid model when dragging" (off by default), draws those shells opaque in their filament colours instead of the toolpaths while the user drags. The visible layer range still holds. The shells are cut at the range's top and bottom through the gouraud shader's z range, and libvgcode keeps a second index buffer holding just the range's bottom and top layers, filled in the same walk as the full one, which is drawn afterwards so that it caps the cut with what was really printed there. Switching between the two sets is a buffer binding, never a rebuild. The prime tower is added to the shells from its sliced mesh while the preference is on, positioned as the print placed it; it keeps its opaque colour and so stays out of the translucent ghost. Supports have no mesh and are not shown. Dragging is the camera, the navigator or either slider being held; a slider reports it from ImGui's active id, since its dirty flag is raised and consumed inside one frame. A wheel step holds the solid model for a 150 ms settle time, with the frame that restores the toolpaths scheduled for when it runs out. The switch is decided at the top of the frame, before the cached scene is consulted, and a frame that switches redraws the scene. A drag cut short by focus or capture loss is ended explicitly, and a button release wakes the idle loop, since on some platforms no idle event follows it until the next input. With the preference off, nothing is built and the preview is unchanged.
246 lines
9.4 KiB
C++
246 lines
9.4 KiB
C++
#ifndef slic3r_GUI_IMSlider_hpp_
|
|
#define slic3r_GUI_IMSlider_hpp_
|
|
|
|
#include "TickCode.hpp"
|
|
#include <imgui/imgui.h>
|
|
#include <wx/slider.h>
|
|
|
|
#include <set>
|
|
|
|
class wxMenu;
|
|
struct IMGUI_API ImRect;
|
|
|
|
namespace Slic3r {
|
|
|
|
using namespace CustomGCode;
|
|
class PrintObject;
|
|
class Layer;
|
|
|
|
namespace GUI {
|
|
|
|
/* For exporting GCode in GCodeWriter is used XYZF_NUM(val) = PRECISION(val, 3) for XYZ values.
|
|
* So, let use same value as a permissible error for layer height.
|
|
*/
|
|
constexpr double epsilon() { return 0.0011; }
|
|
|
|
bool equivalent_areas(const double &bottom_area, const double &top_area);
|
|
|
|
// return true if color change was detected
|
|
bool check_color_change(PrintObject* object, size_t frst_layer_id, size_t layers_cnt, bool check_overhangs,
|
|
// what to do with detected color change
|
|
// and return true when detection have to be desturbed
|
|
std::function<bool(Layer*)> break_condition);
|
|
|
|
enum SelectedSlider {
|
|
ssUndef = 0,
|
|
ssLower = 1,
|
|
ssHigher = 2
|
|
};
|
|
|
|
enum DrawMode
|
|
{
|
|
dmRegular,
|
|
dmSlaPrint,
|
|
dmSequentialFffPrint,
|
|
dmSequentialGCodeView,
|
|
};
|
|
|
|
enum LabelType
|
|
{
|
|
ltHeightWithLayer,
|
|
ltHeight,
|
|
ltEstimatedTime,
|
|
};
|
|
|
|
class IMSlider
|
|
{
|
|
public:
|
|
IMSlider(int lowerValue, int higherValue, int minValue, int maxValue, long style = wxSL_VERTICAL);
|
|
|
|
bool init_texture();
|
|
|
|
~IMSlider() {}
|
|
|
|
int GetMinValue() const { return m_min_value; }
|
|
int GetMaxValue() const { return m_max_value; }
|
|
double GetMinValueD() { return m_values.empty() ? 0. : m_values[m_min_value]; }
|
|
double GetMaxValueD() { return m_values.empty() ? 0. : m_values[m_max_value]; }
|
|
int GetLowerValue() const { return m_lower_value; }
|
|
int GetHigherValue() const { return m_higher_value; }
|
|
int GetActiveValue() const;
|
|
double GetLowerValueD() { return get_double_value(ssLower); }
|
|
double GetHigherValueD() { return get_double_value(ssHigher); }
|
|
SelectedSlider GetSelection() { return m_selection; }
|
|
|
|
// Set low and high slider position. If the span is non-empty, disable the "one layer" mode.
|
|
void SetLowerValue(const int lower_val);
|
|
void SetHigherValue(const int higher_val);
|
|
void SetSelectionSpan(const int lower_val, const int higher_val);
|
|
void SetMaxValue(const int max_value);
|
|
void SetKoefForLabels(const double koef) { m_label_koef = koef; }
|
|
void SetSliderValues(const std::vector<double> &values);
|
|
void SetSliderAlternateValues(const std::vector<double> &values) { m_alternate_values = values; }
|
|
|
|
Info GetTicksValues() const;
|
|
void SetTicksValues(const Info &custom_gcode_per_print_z);
|
|
void SetLayersTimes(const std::vector<float> &layers_times, float total_time);
|
|
void SetLayersTimes(const std::vector<double> &layers_times);
|
|
|
|
void SetDrawMode(bool is_sequential_print);
|
|
void SetDrawMode(DrawMode mode) { m_draw_mode = mode; }
|
|
//BBS
|
|
void SetExtraStyle(long style) { m_extra_style = style; }
|
|
void SetManipulationMode(Mode mode) { m_mode = mode; }
|
|
Mode GetManipulationMode() const { return m_mode; }
|
|
void SetModeAndOnlyExtruder(const bool is_one_extruder_printed_model, const int only_extruder, bool can_change_color);
|
|
void SetExtruderColors(const std::vector<std::string> &extruder_colors);
|
|
|
|
bool IsNewPrint();
|
|
|
|
void set_render_as_disabled(bool value) { m_render_as_disabled = value; }
|
|
bool is_rendering_as_disabled() const { return m_render_as_disabled; }
|
|
|
|
bool is_horizontal() const { return m_style == wxSL_HORIZONTAL; }
|
|
bool is_one_layer() const { return m_is_one_layer; }
|
|
bool is_lower_at_min() const { return m_lower_value == m_min_value; }
|
|
bool is_higher_at_max() const { return m_higher_value == m_max_value; }
|
|
bool is_full_span() const { return this->is_lower_at_min() && this->is_higher_at_max(); }
|
|
|
|
void UseDefaultColors(bool def_colors_on) { m_ticks.set_default_colors(def_colors_on); }
|
|
|
|
void on_mouse_wheel(wxMouseEvent& evt);
|
|
void post_ticks_changed_event(Type type = Unknown);
|
|
bool check_ticks_changed_event(Type type);
|
|
bool switch_one_layer_mode();
|
|
void show_go_to_layer(bool show) { m_show_go_to_layer_dialog = show; }
|
|
|
|
bool render(int canvas_width, int canvas_height);
|
|
|
|
//BBS update scroll value changed
|
|
bool is_dirty() { return m_dirty; }
|
|
// whether the mouse is holding this slider's handle, read from ImGui's active id rather than
|
|
// from the dirty flag, which is raised and consumed inside a single frame
|
|
bool is_dragging() const;
|
|
void set_as_dirty(bool dirty = true) { m_dirty = dirty; }
|
|
bool is_need_post_tick_event() { return m_is_need_post_tick_changed_event; }
|
|
void reset_post_tick_event(bool val = false) {
|
|
m_is_need_post_tick_changed_event = val;
|
|
m_tick_change_event_type = Type::Unknown;
|
|
}
|
|
Type get_post_tick_event_type() { return m_tick_change_event_type; }
|
|
|
|
float m_scale = 1.0;
|
|
void set_scale(float scale = 1.0);
|
|
// ORCA: expose vertical slider width for right-margin alignment in the preview UI.
|
|
static float vertical_slider_window_width();
|
|
void on_change_color_mode(bool is_dark);
|
|
void set_menu_enable(bool enable = true) { m_menu_enable = enable; }
|
|
|
|
protected:
|
|
void add_custom_gcode(std::string custom_gcode);
|
|
void add_code_as_tick(Type type, int selected_extruder = -1);
|
|
void delete_tick(const TickCode& tick);
|
|
void do_go_to_layer(size_t layer_number); //menu
|
|
void correct_lower_value();
|
|
void correct_higher_value();
|
|
bool horizontal_slider(const char* str_id, int* v, int v_min, int v_max, const ImVec2& size, float scale = 1.0);
|
|
void render_go_to_layer_dialog(); //menu
|
|
void render_input_custom_gcode(std::string custom_gcode = ""); //menu
|
|
void render_menu();
|
|
void render_add_menu(); //menu
|
|
void render_edit_menu(const TickCode& tick); //menu
|
|
void draw_background_and_groove(const ImRect& bg_rect, const ImRect& groove);
|
|
void draw_colored_band(const ImRect& groove, const ImRect& slideable_region);
|
|
void draw_custom_label_block(const ImVec2 anchor, Type type);
|
|
void draw_ticks(const ImRect& slideable_region);
|
|
void draw_tick_on_mouse_position(const ImRect& slideable_region);
|
|
void show_tooltip(const TickCode& tick); //menu
|
|
void show_tooltip(const std::string tooltip); //menu
|
|
bool vertical_slider(const char* str_id, int* higher_value, int* lower_value,
|
|
std::string& higher_label, std::string& lower_label,
|
|
int v_min, int v_max, const ImVec2& size,
|
|
SelectedSlider& selection, bool one_layer_flag = false, float scale = 1.0f);
|
|
bool is_wipe_tower_layer(int tick) const;
|
|
|
|
private:
|
|
std::string get_label(int tick, LabelType label_type = ltHeightWithLayer);
|
|
double get_double_value(const SelectedSlider& selection);
|
|
int get_tick_from_value(double value, bool force_lower_bound = false);
|
|
float get_pos_from_value(int v_min, int v_max, int value, const ImRect& rect);
|
|
int get_tick_near_point(int v_min, int v_max, const ImVec2& pt, const ImRect& rect);
|
|
|
|
std::string get_color_for_tool_change_tick(std::set<TickCode>::const_iterator it) const;
|
|
// Get active extruders for tick.
|
|
// Means one current extruder for not existing tick OR
|
|
// 2 extruders - for existing tick (extruder before ToolChangeCode and extruder of current existing tick)
|
|
// Use those values to disable selection of active extruders
|
|
std::array<int, 2> get_active_extruders_for_tick(int tick) const;
|
|
|
|
// Use those values to disable selection of active extruders
|
|
bool m_is_dark = false;
|
|
|
|
int m_min_value;
|
|
int m_max_value;
|
|
int m_lower_value;
|
|
int m_higher_value;
|
|
int m_one_layer_value; // ORCA
|
|
bool m_dirty = false;
|
|
// the ImGui id of the slider widget, as of its last render
|
|
unsigned int m_imgui_id = 0;
|
|
|
|
bool m_render_as_disabled{ false };
|
|
|
|
SelectedSlider m_selection;
|
|
bool m_is_one_layer = false;
|
|
bool m_menu_enable = true; //menu
|
|
bool m_show_menu = false; //menu
|
|
bool m_show_custom_gcode_window = false; //menu
|
|
bool m_show_go_to_layer_dialog = false; //menu
|
|
bool m_force_mode_apply = true;
|
|
bool m_is_wipe_tower = false; // This flag indicates that there is multiple extruder print with wipe tower
|
|
bool m_is_spiral_vase = false;
|
|
|
|
/* BBS slider images */
|
|
void *m_one_layer_on_id;
|
|
void *m_one_layer_on_hover_id;
|
|
void *m_one_layer_off_id;
|
|
void *m_one_layer_off_hover_id;
|
|
void* m_one_layer_on_dark_id;
|
|
void* m_one_layer_on_hover_dark_id;
|
|
void* m_one_layer_off_dark_id;
|
|
void* m_one_layer_off_hover_dark_id;
|
|
void *m_pause_icon_id;
|
|
void *m_custom_icon_id;
|
|
void *m_delete_icon_id;
|
|
|
|
DrawMode m_draw_mode = dmRegular;
|
|
Mode m_mode = SingleExtruder;
|
|
int m_only_extruder = -1;
|
|
|
|
long m_style;
|
|
long m_extra_style;
|
|
float m_label_koef{1.0};
|
|
|
|
std::vector<double> m_values;
|
|
TickCodeInfo m_ticks;
|
|
std::vector<double> m_layers_times;
|
|
std::vector<double> m_layers_values;
|
|
std::vector<std::string> m_extruder_colors;
|
|
bool m_can_change_color;
|
|
std::string m_print_obj_idxs;
|
|
bool m_is_need_post_tick_changed_event { false };
|
|
Type m_tick_change_event_type;
|
|
|
|
std::vector<double> m_alternate_values;
|
|
|
|
char m_custom_gcode[1024] = { 0 }; //menu
|
|
char m_layer_number[64] = { 0 }; //menu
|
|
};
|
|
|
|
}
|
|
|
|
} // Slic3r
|
|
|
|
|
|
#endif // slic3r_GUI_IMSlider_hpp_
|