diff options
author | Enrico Turri <enricoturri@seznam.cz> | 2018-07-31 13:25:00 +0300 |
---|---|---|
committer | Enrico Turri <enricoturri@seznam.cz> | 2018-07-31 13:25:00 +0300 |
commit | 1c0fa198245eb27554b85b82e1b4fa43c7f18a3e (patch) | |
tree | e6a1cb75750370e1fd944191716c0f35c1c4c6e5 /xs | |
parent | 55e7a1af4621dc8c09e9bdff8f5a6d5d8d5b00e6 (diff) |
3D scene toolbar uses a single texture
Diffstat (limited to 'xs')
-rw-r--r-- | xs/src/slic3r/GUI/GLCanvas3D.cpp | 128 | ||||
-rw-r--r-- | xs/src/slic3r/GUI/GLCanvas3D.hpp | 4 | ||||
-rw-r--r-- | xs/src/slic3r/GUI/GLTexture.cpp | 41 | ||||
-rw-r--r-- | xs/src/slic3r/GUI/GLTexture.hpp | 22 | ||||
-rw-r--r-- | xs/src/slic3r/GUI/GLToolbar.cpp | 614 | ||||
-rw-r--r-- | xs/src/slic3r/GUI/GLToolbar.hpp | 116 |
6 files changed, 672 insertions, 253 deletions
diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 38e87abca..736f6431d 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -3288,53 +3288,49 @@ bool GLCanvas3D::_init_toolbar() if (!m_toolbar.is_enabled()) return true; - GLToolbar::ItemCreationData item; + if (!m_toolbar.init("toolbar.png", 36, 1, 1)) + { + // unable to init the toolbar texture, disable it + m_toolbar.set_enabled(false); + return true; + } + +// m_toolbar.set_layout_type(GLToolbar::Layout::Vertical); + m_toolbar.set_layout_type(GLToolbar::Layout::Horizontal); + m_toolbar.set_separator_size(5); + m_toolbar.set_gap_size(2); + + GLToolbarItem::Data item; item.name = "add"; item.tooltip = GUI::L_str("Add..."); + item.sprite_id = 0; item.is_toggable = false; item.action_callback = &m_action_add_callback; - item.textures[GLToolbarItem::Normal] = "brick_add_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "brick_add_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "brick_add_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "brick_add_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "brick_add_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "delete"; item.tooltip = GUI::L_str("Delete"); + item.sprite_id = 1; item.is_toggable = false; item.action_callback = &m_action_delete_callback; - item.textures[GLToolbarItem::Normal] = "brick_delete_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "brick_delete_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "brick_delete_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "brick_delete_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "brick_delete_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "deleteall"; item.tooltip = GUI::L_str("Delete all"); + item.sprite_id = 2; item.is_toggable = false; item.action_callback = &m_action_deleteall_callback; - item.textures[GLToolbarItem::Normal] = "cross_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "cross_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "cross_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "cross_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "cross_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "arrange"; item.tooltip = GUI::L_str("Arrange"); + item.sprite_id = 3; item.is_toggable = false; item.action_callback = &m_action_arrange_callback; - item.textures[GLToolbarItem::Normal] = "bricks_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "bricks_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "bricks_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "bricks_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "bricks_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; @@ -3343,25 +3339,17 @@ bool GLCanvas3D::_init_toolbar() item.name = "more"; item.tooltip = GUI::L_str("Add instance"); + item.sprite_id = 4; item.is_toggable = false; item.action_callback = &m_action_more_callback; - item.textures[GLToolbarItem::Normal] = "add_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "add_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "add_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "add_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "add_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "fewer"; item.tooltip = GUI::L_str("Remove instance"); + item.sprite_id = 5; item.is_toggable = false; item.action_callback = &m_action_fewer_callback; - item.textures[GLToolbarItem::Normal] = "delete_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "delete_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "delete_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "delete_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "delete_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; @@ -3370,61 +3358,41 @@ bool GLCanvas3D::_init_toolbar() item.name = "ccw45"; item.tooltip = GUI::L_str("Rotate CCW 45 degrees"); + item.sprite_id = 6; item.is_toggable = false; item.action_callback = &m_action_ccw45_callback; - item.textures[GLToolbarItem::Normal] = "arrow_rotate_anticlockwise_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "arrow_rotate_anticlockwise_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "arrow_rotate_anticlockwise_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "arrow_rotate_anticlockwise_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "arrow_rotate_anticlockwise_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "cw45"; item.tooltip = GUI::L_str("Rotate CW 45 degrees"); + item.sprite_id = 7; item.is_toggable = false; item.action_callback = &m_action_cw45_callback; - item.textures[GLToolbarItem::Normal] = "arrow_rotate_clockwise_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "arrow_rotate_clockwise_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "arrow_rotate_clockwise_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "arrow_rotate_clockwise_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "arrow_rotate_clockwise_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "scale"; item.tooltip = GUI::L_str("Scale..."); + item.sprite_id = 8; item.is_toggable = false; item.action_callback = &m_action_scale_callback; - item.textures[GLToolbarItem::Normal] = "arrow_out_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "arrow_out_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "arrow_out_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "arrow_out_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "arrow_out_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "split"; item.tooltip = GUI::L_str("Split"); + item.sprite_id = 9; item.is_toggable = false; item.action_callback = &m_action_split_callback; - item.textures[GLToolbarItem::Normal] = "shape_ungroup_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "shape_ungroup_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "shape_ungroup_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "shape_ungroup_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "shape_ungroup_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "cut"; item.tooltip = GUI::L_str("Cut..."); + item.sprite_id = 10; item.is_toggable = false; item.action_callback = &m_action_cut_callback; - item.textures[GLToolbarItem::Normal] = "package_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "package_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "package_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "package_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "package_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; @@ -3433,25 +3401,17 @@ bool GLCanvas3D::_init_toolbar() item.name = "settings"; item.tooltip = GUI::L_str("Settings..."); + item.sprite_id = 11; item.is_toggable = false; item.action_callback = &m_action_settings_callback; - item.textures[GLToolbarItem::Normal] = "cog_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "cog_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "cog_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "cog_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "cog_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "layersediting"; item.tooltip = GUI::L_str("Layers editing"); + item.sprite_id = 12; item.is_toggable = true; item.action_callback = &m_action_layersediting_callback; - item.textures[GLToolbarItem::Normal] = "variable_layer_height_normal_36.png"; - item.textures[GLToolbarItem::Hover] = "variable_layer_height_hover_36.png"; - item.textures[GLToolbarItem::Pressed] = "variable_layer_height_pressed_36.png"; - item.textures[GLToolbarItem::HoverPressed] = "variable_layer_height_hover_pressed_36.png"; - item.textures[GLToolbarItem::Disabled] = "variable_layer_height_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; @@ -4067,7 +4027,8 @@ void GLCanvas3D::_render_gizmo() const //################################################################################################################################### void GLCanvas3D::_render_toolbar() const { - m_toolbar.render(m_mouse.position); + _resize_toolbar(); + m_toolbar.render(); } //################################################################################################################################### @@ -5301,5 +5262,38 @@ bool GLCanvas3D::_is_any_volume_outside() const return false; } +//################################################################################################################################### +void GLCanvas3D::_resize_toolbar() const +{ + Size cnv_size = get_canvas_size(); + float zoom = get_camera_zoom(); + float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + + switch (m_toolbar.get_layout_type()) + { + default: + case GLToolbar::Layout::Horizontal: + { + // centers the toolbar on the top edge of the 3d scene + unsigned int toolbar_width = m_toolbar.get_width(); + float top = (0.5f * (float)cnv_size.get_height() - 2.0f) * inv_zoom; + float left = -0.5f * (float)toolbar_width * inv_zoom; + m_toolbar.set_position(top, left); + break; + } + case GLToolbar::Layout::Vertical: + { + // centers the toolbar on the right edge of the 3d scene + unsigned int toolbar_width = m_toolbar.get_width(); + unsigned int toolbar_height = m_toolbar.get_height(); + float top = 0.5f * (float)toolbar_height * inv_zoom; + float left = (0.5f * (float)cnv_size.get_width() - toolbar_width - 2.0f) * inv_zoom; + m_toolbar.set_position(top, left); + break; + } + } +} +//################################################################################################################################### + } // namespace GUI } // namespace Slic3r diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index a2614a976..b026acd13 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -746,6 +746,10 @@ private: bool _is_any_volume_outside() const; +//################################################################################################################################### + void _resize_toolbar() const; +//################################################################################################################################### + static std::vector<float> _parse_colors(const std::vector<std::string>& colors); }; diff --git a/xs/src/slic3r/GUI/GLTexture.cpp b/xs/src/slic3r/GUI/GLTexture.cpp index 18c9f5dea..03890d780 100644 --- a/xs/src/slic3r/GUI/GLTexture.cpp +++ b/xs/src/slic3r/GUI/GLTexture.cpp @@ -12,6 +12,10 @@ namespace Slic3r { namespace GUI { +//################################################################################################################################### +GLTexture::Quad_UVs GLTexture::FullTextureUVs = { { 0.0f, 1.0f }, { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 0.0f, 0.0f } }; +//################################################################################################################################### + GLTexture::GLTexture() : m_id(0) , m_width(0) @@ -129,6 +133,34 @@ const std::string& GLTexture::get_source() const void GLTexture::render_texture(unsigned int tex_id, float left, float right, float bottom, float top) { +//################################################################################################################################### + render_sub_texture(tex_id, left, right, bottom, top, FullTextureUVs); + +// ::glEnable(GL_BLEND); +// ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +// +// ::glEnable(GL_TEXTURE_2D); +// ::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +// +// ::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id); +// +// ::glBegin(GL_QUADS); +// ::glTexCoord2f(0.0f, 1.0f); ::glVertex2f(left, bottom); +// ::glTexCoord2f(1.0f, 1.0f); ::glVertex2f(right, bottom); +// ::glTexCoord2f(1.0f, 0.0f); ::glVertex2f(right, top); +// ::glTexCoord2f(0.0f, 0.0f); ::glVertex2f(left, top); +// ::glEnd(); +// +// ::glBindTexture(GL_TEXTURE_2D, 0); +// +// ::glDisable(GL_TEXTURE_2D); +// ::glDisable(GL_BLEND); +//################################################################################################################################### +} + +//################################################################################################################################### +void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right, float bottom, float top, const GLTexture::Quad_UVs& uvs) +{ ::glEnable(GL_BLEND); ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -138,10 +170,10 @@ void GLTexture::render_texture(unsigned int tex_id, float left, float right, flo ::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id); ::glBegin(GL_QUADS); - ::glTexCoord2f(0.0f, 1.0f); ::glVertex2f(left, bottom); - ::glTexCoord2f(1.0f, 1.0f); ::glVertex2f(right, bottom); - ::glTexCoord2f(1.0f, 0.0f); ::glVertex2f(right, top); - ::glTexCoord2f(0.0f, 0.0f); ::glVertex2f(left, top); + ::glTexCoord2f(uvs.left_bottom.u, uvs.left_bottom.v); ::glVertex2f(left, bottom); + ::glTexCoord2f(uvs.right_bottom.u, uvs.right_bottom.v); ::glVertex2f(right, bottom); + ::glTexCoord2f(uvs.right_top.u, uvs.right_top.v); ::glVertex2f(right, top); + ::glTexCoord2f(uvs.left_top.u, uvs.left_top.v); ::glVertex2f(left, top); ::glEnd(); ::glBindTexture(GL_TEXTURE_2D, 0); @@ -149,6 +181,7 @@ void GLTexture::render_texture(unsigned int tex_id, float left, float right, flo ::glDisable(GL_TEXTURE_2D); ::glDisable(GL_BLEND); } +//################################################################################################################################### unsigned int GLTexture::_generate_mipmaps(wxImage& image) { diff --git a/xs/src/slic3r/GUI/GLTexture.hpp b/xs/src/slic3r/GUI/GLTexture.hpp index 3113fcab2..a7d610200 100644 --- a/xs/src/slic3r/GUI/GLTexture.hpp +++ b/xs/src/slic3r/GUI/GLTexture.hpp @@ -10,6 +10,25 @@ namespace GUI { class GLTexture { +//################################################################################################################################### + public: + struct UV + { + float u; + float v; + }; + + struct Quad_UVs + { + UV left_bottom; + UV right_bottom; + UV right_top; + UV left_top; + }; + + static Quad_UVs FullTextureUVs; +//################################################################################################################################### + protected: unsigned int m_id; int m_width; @@ -30,6 +49,9 @@ namespace GUI { const std::string& get_source() const; static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top); +//################################################################################################################################### + static void render_sub_texture(unsigned int tex_id, float left, float right, float bottom, float top, const Quad_UVs& uvs); +//################################################################################################################################### protected: unsigned int _generate_mipmaps(wxImage& image); diff --git a/xs/src/slic3r/GUI/GLToolbar.cpp b/xs/src/slic3r/GUI/GLToolbar.cpp index c425164a2..fd993f5a2 100644 --- a/xs/src/slic3r/GUI/GLToolbar.cpp +++ b/xs/src/slic3r/GUI/GLToolbar.cpp @@ -11,34 +11,20 @@ namespace Slic3r { namespace GUI { -GLToolbarItem::GLToolbarItem(EType type, const std::string& name, const std::string& tooltip, bool is_toggable, PerlCallback* action_callback) - : m_type(type) - , m_state(Disabled) - , m_name(name) - , m_tooltip(tooltip) - , m_is_toggable(is_toggable) - , m_action_callback(action_callback) +GLToolbarItem::Data::Data() + : name("") + , tooltip("") + , sprite_id(-1) + , is_toggable(false) + , action_callback(nullptr) { } -bool GLToolbarItem::load_textures(const std::string* filenames) +GLToolbarItem::GLToolbarItem(GLToolbarItem::EType type, const GLToolbarItem::Data& data) + : m_type(type) + , m_state(Disabled) + , m_data(data) { - if (filenames == nullptr) - return false; - - std::string path = resources_dir() + "/icons/"; - - for (unsigned int i = (unsigned int)Normal; i < (unsigned int)Num_States; ++i) - { - if (!filenames[i].empty()) - { - std::string filename = path + filenames[i]; - if (!m_icon_textures[i].load_from_file(filename, false)) - return false; - } - } - - return true; } GLToolbarItem::EState GLToolbarItem::get_state() const @@ -53,28 +39,18 @@ void GLToolbarItem::set_state(GLToolbarItem::EState state) const std::string& GLToolbarItem::get_name() const { - return m_name; + return m_data.name; } const std::string& GLToolbarItem::get_tooltip() const { - return m_tooltip; -} - -unsigned int GLToolbarItem::get_icon_texture_id() const -{ - return m_icon_textures[m_state].get_id(); -} - -int GLToolbarItem::get_icon_textures_size() const -{ - return m_icon_textures[Normal].get_width(); + return m_data.tooltip; } void GLToolbarItem::do_action() { - if (m_action_callback != nullptr) - m_action_callback->call(); + if (m_data.action_callback != nullptr) + m_data.action_callback->call(); } bool GLToolbarItem::is_enabled() const @@ -94,7 +70,7 @@ bool GLToolbarItem::is_pressed() const bool GLToolbarItem::is_toggable() const { - return m_is_toggable; + return m_data.is_toggable; } bool GLToolbarItem::is_separator() const @@ -102,60 +78,121 @@ bool GLToolbarItem::is_separator() const return m_type == Separator; } +void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int texture_size, unsigned int border_size, unsigned int icon_size, unsigned int gap_size) const +{ + GLTexture::render_sub_texture(tex_id, left, right, bottom, top, _get_uvs(texture_size, border_size, icon_size, gap_size)); +} + +GLTexture::Quad_UVs GLToolbarItem::_get_uvs(unsigned int texture_size, unsigned int border_size, unsigned int icon_size, unsigned int gap_size) const +{ + GLTexture::Quad_UVs uvs; + + float inv_texture_size = (texture_size != 0) ? 1.0f / (float)texture_size : 0.0f; + + float scaled_icon_size = (float)icon_size * inv_texture_size; + float scaled_border_size = (float)border_size * inv_texture_size; + float scaled_gap_size = (float)gap_size * inv_texture_size; + float stride = scaled_icon_size + scaled_gap_size; + + float left = scaled_border_size + (float)m_state * stride; + float right = left + scaled_icon_size; + float top = scaled_border_size + (float)m_data.sprite_id * stride; + float bottom = top + scaled_icon_size; + + uvs.left_top = { left, top }; + uvs.left_bottom = { left, bottom }; + uvs.right_bottom = { right, bottom }; + uvs.right_top = { right, top }; + + return uvs; +} + +GLToolbar::ItemsIconsTexture::ItemsIconsTexture() + : items_icon_size(0) + , items_icon_border_size(0) + , items_icon_gap_size(0) +{ +} + +GLToolbar::Layout::Layout() + : type(Horizontal) + , top(0.0f) + , left(0.0f) + , separator_size(0.0f) + , gap_size(0.0f) +{ +} + GLToolbar::GLToolbar(GLCanvas3D& parent) : m_parent(parent) , m_enabled(false) - , m_textures_scale(1.0f) - , m_offset_y(5.0f) - , m_gap_x(2.0f) - , m_separator_x(5.0f) { } -bool GLToolbar::is_enabled() const +bool GLToolbar::init(const std::string& icons_texture_filename, unsigned int items_icon_size, unsigned int items_icon_border_size, unsigned int items_icon_gap_size) { - return m_enabled; + std::string path = resources_dir() + "/icons/"; + bool res = !icons_texture_filename.empty() && m_icons_texture.texture.load_from_file(path + icons_texture_filename, false); + if (res) + { + m_icons_texture.items_icon_size = items_icon_size; + m_icons_texture.items_icon_border_size = items_icon_border_size; + m_icons_texture.items_icon_gap_size = items_icon_gap_size; + } + + return res; } -void GLToolbar::set_enabled(bool enable) +GLToolbar::Layout::Type GLToolbar::get_layout_type() const { - m_enabled = true; + return m_layout.type; } -void GLToolbar::set_textures_scale(float scale) +void GLToolbar::set_layout_type(GLToolbar::Layout::Type type) { - m_textures_scale = scale; + m_layout.type = type; } -void GLToolbar::set_offset_y(float offset) +void GLToolbar::set_position(float top, float left) { - m_offset_y = offset; + m_layout.top = top; + m_layout.left = left; } -void GLToolbar::set_gap_x(float gap) +void GLToolbar::set_separator_size(float size) { - m_gap_x = gap; + m_layout.separator_size = size; } -void GLToolbar::set_separator_x(float separator) +void GLToolbar::set_gap_size(float size) { - m_separator_x = separator; + m_layout.gap_size = size; } -bool GLToolbar::add_item(const GLToolbar::ItemCreationData& data) +bool GLToolbar::is_enabled() const +{ + return m_enabled; +} + +void GLToolbar::set_enabled(bool enable) +{ + m_enabled = true; +} + +bool GLToolbar::add_item(const GLToolbarItem::Data& data) { - GLToolbarItem* item = new GLToolbarItem(GLToolbarItem::Action, data.name, data.tooltip, data.is_toggable, data.action_callback); - if ((item == nullptr) || !item->load_textures(data.textures)) + GLToolbarItem* item = new GLToolbarItem(GLToolbarItem::Action, data); + if (item == nullptr) return false; m_items.push_back(item); - return true; } bool GLToolbar::add_separator() { - GLToolbarItem* item = new GLToolbarItem(GLToolbarItem::Separator, "", "", false, nullptr); + GLToolbarItem::Data data; + GLToolbarItem* item = new GLToolbarItem(GLToolbarItem::Separator, data); if (item == nullptr) return false; @@ -163,6 +200,38 @@ bool GLToolbar::add_separator() return true; } +float GLToolbar::get_width() const +{ + switch (m_layout.type) + { + default: + case Layout::Horizontal: + { + return _get_width_horizontal(); + } + case Layout::Vertical: + { + return _get_width_vertical(); + } + } +} + +float GLToolbar::get_height() const +{ + switch (m_layout.type) + { + default: + case Layout::Horizontal: + { + return _get_height_horizontal(); + } + case Layout::Vertical: + { + return _get_height_vertical(); + } + } +} + void GLToolbar::enable_item(const std::string& name) { for (GLToolbarItem* item : m_items) @@ -203,25 +272,252 @@ void GLToolbar::update_hover_state(const Pointf& mouse_pos) if (!m_enabled) return; - float cnv_w = (float)m_parent.get_canvas_size().get_width(); - float width = _get_total_width(); - float left = 0.5f * (cnv_w - width); - float top = m_offset_y; + switch (m_layout.type) + { + default: + case Layout::Horizontal: + { + _update_hover_state_horizontal(mouse_pos); + break; + } + case Layout::Vertical: + { + _update_hover_state_vertical(mouse_pos); + break; + } + } +} + +int GLToolbar::contains_mouse(const Pointf& mouse_pos) const +{ + if (!m_enabled) + return -1; + + switch (m_layout.type) + { + default: + case Layout::Horizontal: + { + return _contains_mouse_horizontal(mouse_pos); + } + case Layout::Vertical: + { + return _contains_mouse_vertical(mouse_pos); + } + } +} + +void GLToolbar::do_action(unsigned int item_id) +{ + if (item_id < (unsigned int)m_items.size()) + { + GLToolbarItem* item = m_items[item_id]; + if ((item != nullptr) && !item->is_separator() && item->is_hovered()) + { + if (item->is_toggable()) + { + GLToolbarItem::EState state = item->get_state(); + if (state == GLToolbarItem::Hover) + item->set_state(GLToolbarItem::HoverPressed); + else if (state == GLToolbarItem::HoverPressed) + item->set_state(GLToolbarItem::Hover); + + m_parent.render(); + item->do_action(); + } + else + { + item->set_state(GLToolbarItem::HoverPressed); + m_parent.render(); + item->do_action(); + if (item->get_state() != GLToolbarItem::Disabled) + { + // the item may get disabled during the action, if not, set it back to hover state + item->set_state(GLToolbarItem::Hover); + m_parent.render(); + } + } + } + } +} + +void GLToolbar::render() const +//void GLToolbar::render(const Pointf& mouse_pos) const +{ + if (!m_enabled || m_items.empty()) + return; + + ::glDisable(GL_DEPTH_TEST); + + ::glPushMatrix(); + ::glLoadIdentity(); + + switch (m_layout.type) + { + default: + case Layout::Horizontal: + { + _render_horizontal(); + break; + } + case Layout::Vertical: + { + _render_vertical(); + break; + } + } + + ::glPopMatrix(); +} + +float GLToolbar::_get_width_horizontal() const +{ + return _get_main_size(); +} + +float GLToolbar::_get_width_vertical() const +{ + return m_icons_texture.items_icon_size; +} + +float GLToolbar::_get_height_horizontal() const +{ + return m_icons_texture.items_icon_size; +} + +float GLToolbar::_get_height_vertical() const +{ + return _get_main_size(); +} + +float GLToolbar::_get_main_size() const +{ + float size = 0.0f; + for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) + { + if (m_items[i]->is_separator()) + size += m_layout.separator_size; + else + size += (float)m_icons_texture.items_icon_size; + } + + if (m_items.size() > 1) + size += ((float)m_items.size() - 1.0f) * m_layout.gap_size; + + return size; +} + +void GLToolbar::_update_hover_state_horizontal(const Pointf& mouse_pos) +{ + float zoom = m_parent.get_camera_zoom(); + float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + + Size cnv_size = m_parent.get_canvas_size(); + Pointf scaled_mouse_pos((mouse_pos.x - 0.5f * (float)cnv_size.get_width()) * inv_zoom, (0.5f * (float)cnv_size.get_height() - mouse_pos.y) * inv_zoom); + + float scaled_icons_size = (float)m_icons_texture.items_icon_size * inv_zoom; + float scaled_separator_size = m_layout.separator_size * inv_zoom; + float scaled_gap_size = m_layout.gap_size * inv_zoom; + + float separator_stride = scaled_separator_size + scaled_gap_size; + float icon_stride = scaled_icons_size + scaled_gap_size; + + float left = m_layout.left; + float top = m_layout.top; + + std::string tooltip = ""; + + for (GLToolbarItem* item : m_items) + { + if (item->is_separator()) + left += separator_stride; + else + { + float right = left + scaled_icons_size; + float bottom = top - scaled_icons_size; + + GLToolbarItem::EState state = item->get_state(); + bool inside = (left <= scaled_mouse_pos.x) && (scaled_mouse_pos.x <= right) && (bottom <= scaled_mouse_pos.y) && (scaled_mouse_pos.y <= top); + + switch (state) + { + case GLToolbarItem::Normal: + { + if (inside) + item->set_state(GLToolbarItem::Hover); + + break; + } + case GLToolbarItem::Hover: + { + if (inside) + tooltip = item->get_tooltip(); + else + item->set_state(GLToolbarItem::Normal); + + break; + } + case GLToolbarItem::Pressed: + { + if (inside) + item->set_state(GLToolbarItem::HoverPressed); + + break; + } + case GLToolbarItem::HoverPressed: + { + if (inside) + tooltip = item->get_tooltip(); + else + item->set_state(GLToolbarItem::Pressed); + + break; + } + default: + case GLToolbarItem::Disabled: + { + break; + } + } + + left += icon_stride; + } + } + + m_parent.set_tooltip(tooltip); +} + +void GLToolbar::_update_hover_state_vertical(const Pointf& mouse_pos) +{ + float zoom = m_parent.get_camera_zoom(); + float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + + Size cnv_size = m_parent.get_canvas_size(); + Pointf scaled_mouse_pos((mouse_pos.x - 0.5f * (float)cnv_size.get_width()) * inv_zoom, (0.5f * (float)cnv_size.get_height() - mouse_pos.y) * inv_zoom); + + float scaled_icons_size = (float)m_icons_texture.items_icon_size * inv_zoom; + float scaled_separator_size = m_layout.separator_size * inv_zoom; + float scaled_gap_size = m_layout.gap_size * inv_zoom; + + float separator_stride = scaled_separator_size + scaled_gap_size; + float icon_stride = scaled_icons_size + scaled_gap_size; + + float left = m_layout.left; + float top = m_layout.top; std::string tooltip = ""; for (GLToolbarItem* item : m_items) { if (item->is_separator()) - left += (m_separator_x + m_gap_x); + top -= separator_stride; else { - float tex_size = (float)item->get_icon_textures_size() * m_textures_scale; - float right = left + tex_size; - float bottom = top + tex_size; + float right = left + scaled_icons_size; + float bottom = top - scaled_icons_size; GLToolbarItem::EState state = item->get_state(); - bool inside = (left <= mouse_pos.x) && (mouse_pos.x <= right) && (top <= mouse_pos.y) && (mouse_pos.y <= bottom); + bool inside = (left <= scaled_mouse_pos.x) && (scaled_mouse_pos.x <= right) && (bottom <= scaled_mouse_pos.y) && (scaled_mouse_pos.y <= top); switch (state) { @@ -263,134 +559,162 @@ void GLToolbar::update_hover_state(const Pointf& mouse_pos) break; } } - left += (tex_size + m_gap_x); + + top -= icon_stride; } } m_parent.set_tooltip(tooltip); } -int GLToolbar::contains_mouse(const Pointf& mouse_pos) const +int GLToolbar::_contains_mouse_horizontal(const Pointf& mouse_pos) const { - if (!m_enabled) - return -1; + float zoom = m_parent.get_camera_zoom(); + float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; - float cnv_w = (float)m_parent.get_canvas_size().get_width(); - float width = _get_total_width(); - float left = 0.5f * (cnv_w - width); - float top = m_offset_y; + Size cnv_size = m_parent.get_canvas_size(); + Pointf scaled_mouse_pos((mouse_pos.x - 0.5f * (float)cnv_size.get_width()) * inv_zoom, (0.5f * (float)cnv_size.get_height() - mouse_pos.y) * inv_zoom); - int id = -1; + float scaled_icons_size = (float)m_icons_texture.items_icon_size * inv_zoom; + float scaled_separator_size = m_layout.separator_size * inv_zoom; + float scaled_gap_size = m_layout.gap_size * inv_zoom; + + float separator_stride = scaled_separator_size + scaled_gap_size; + float icon_stride = scaled_icons_size + scaled_gap_size; + + float left = m_layout.left; + float top = m_layout.top; + int id = -1; + for (GLToolbarItem* item : m_items) { ++id; - + if (item->is_separator()) - left += (m_separator_x + m_gap_x); + left += separator_stride; else { - float tex_size = (float)item->get_icon_textures_size() * m_textures_scale; - float right = left + tex_size; - float bottom = top + tex_size; - - if ((left <= mouse_pos.x) && (mouse_pos.x <= right) && (top <= mouse_pos.y) && (mouse_pos.y <= bottom)) + float right = left + scaled_icons_size; + float bottom = top - scaled_icons_size; + + if ((left <= scaled_mouse_pos.x) && (scaled_mouse_pos.x <= right) && (bottom <= scaled_mouse_pos.y) && (scaled_mouse_pos.y <= top)) return id; - - left += (tex_size + m_gap_x); + + left += icon_stride; } } - + return -1; } -void GLToolbar::do_action(unsigned int item_id) +int GLToolbar::_contains_mouse_vertical(const Pointf& mouse_pos) const { - if (item_id < (unsigned int)m_items.size()) + float zoom = m_parent.get_camera_zoom(); + float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + + Size cnv_size = m_parent.get_canvas_size(); + Pointf scaled_mouse_pos((mouse_pos.x - 0.5f * (float)cnv_size.get_width()) * inv_zoom, (0.5f * (float)cnv_size.get_height() - mouse_pos.y) * inv_zoom); + + float scaled_icons_size = (float)m_icons_texture.items_icon_size * inv_zoom; + float scaled_separator_size = m_layout.separator_size * inv_zoom; + float scaled_gap_size = m_layout.gap_size * inv_zoom; + + float separator_stride = scaled_separator_size + scaled_gap_size; + float icon_stride = scaled_icons_size + scaled_gap_size; + + float left = m_layout.left; + float top = m_layout.top; + + int id = -1; + + for (GLToolbarItem* item : m_items) { - GLToolbarItem* item = m_items[item_id]; - if ((item != nullptr) && !item->is_separator() && item->is_hovered()) + ++id; + + if (item->is_separator()) + top -= separator_stride; + else { - if (item->is_toggable()) - { - GLToolbarItem::EState state = item->get_state(); - if (state == GLToolbarItem::Hover) - item->set_state(GLToolbarItem::HoverPressed); - else if (state == GLToolbarItem::HoverPressed) - item->set_state(GLToolbarItem::Hover); + float right = left + scaled_icons_size; + float bottom = top - scaled_icons_size; - m_parent.render(); - item->do_action(); - } - else - { - item->set_state(GLToolbarItem::HoverPressed); - m_parent.render(); - item->do_action(); - if (item->get_state() != GLToolbarItem::Disabled) - { - // the item may get disabled during the action, if not, set it back to hover state - item->set_state(GLToolbarItem::Hover); - m_parent.render(); - } - } + if ((left <= scaled_mouse_pos.x) && (scaled_mouse_pos.x <= right) && (bottom <= scaled_mouse_pos.y) && (scaled_mouse_pos.y <= top)) + return id; + + top -= icon_stride; } } + + return -1; } -void GLToolbar::render(const Pointf& mouse_pos) const +void GLToolbar::_render_horizontal() const { - if (!m_enabled || m_items.empty()) - return; - - ::glDisable(GL_DEPTH_TEST); + unsigned int tex_id = m_icons_texture.texture.get_id(); + int tex_size = m_icons_texture.texture.get_width(); - ::glPushMatrix(); - ::glLoadIdentity(); + if ((tex_id == 0) || (tex_size <= 0)) + return; - float cnv_w = (float)m_parent.get_canvas_size().get_width(); - float cnv_h = (float)m_parent.get_canvas_size().get_height(); float zoom = m_parent.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; - float width = _get_total_width(); - float top_x = -0.5f * width * inv_zoom; - float top_y = (0.5f * cnv_h - m_offset_y * m_textures_scale) * inv_zoom; - float scaled_gap_x = m_gap_x * inv_zoom; - float scaled_separator_x = m_separator_x * inv_zoom; + float scaled_icons_size = (float)m_icons_texture.items_icon_size * inv_zoom; + float scaled_separator_size = m_layout.separator_size * inv_zoom; + float scaled_gap_size = m_layout.gap_size * inv_zoom; + + float separator_stride = scaled_separator_size + scaled_gap_size; + float icon_stride = scaled_icons_size + scaled_gap_size; + + float left = m_layout.left; + float top = m_layout.top; // renders icons for (const GLToolbarItem* item : m_items) { if (item->is_separator()) - top_x += (scaled_separator_x + scaled_gap_x); + left += separator_stride; else { - float tex_size = (float)item->get_icon_textures_size() * m_textures_scale * inv_zoom; - GLTexture::render_texture(item->get_icon_texture_id(), top_x, top_x + tex_size, top_y - tex_size, top_y); - top_x += (tex_size + scaled_gap_x); + item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_size, m_icons_texture.items_icon_border_size, m_icons_texture.items_icon_size, m_icons_texture.items_icon_gap_size); + left += icon_stride; } } - - ::glPopMatrix(); } -float GLToolbar::_get_total_width() const +void GLToolbar::_render_vertical() const { - float width = 0.0f; + unsigned int tex_id = m_icons_texture.texture.get_id(); + int tex_size = m_icons_texture.texture.get_width(); - for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i) + if ((tex_id == 0) || (tex_size <= 0)) + return; + + float zoom = m_parent.get_camera_zoom(); + float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + + float scaled_icons_size = (float)m_icons_texture.items_icon_size * inv_zoom; + float scaled_separator_size = m_layout.separator_size * inv_zoom; + float scaled_gap_size = m_layout.gap_size * inv_zoom; + + float separator_stride = scaled_separator_size + scaled_gap_size; + float icon_stride = scaled_icons_size + scaled_gap_size; + + float left = m_layout.left; + float top = m_layout.top; + + // renders icons + for (const GLToolbarItem* item : m_items) { - if (m_items[i]->is_separator()) - width += m_separator_x; + if (item->is_separator()) + top -= separator_stride; else - width += m_items[i]->get_icon_textures_size(); - - if (i < (unsigned int)m_items.size() - 1) - width += m_gap_x; + { + item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_size, m_icons_texture.items_icon_border_size, m_icons_texture.items_icon_size, m_icons_texture.items_icon_gap_size); + top -= icon_stride; + } } - - return width; } } // namespace GUI diff --git a/xs/src/slic3r/GUI/GLToolbar.hpp b/xs/src/slic3r/GUI/GLToolbar.hpp index d157f2a3b..b6eb6b19c 100644 --- a/xs/src/slic3r/GUI/GLToolbar.hpp +++ b/xs/src/slic3r/GUI/GLToolbar.hpp @@ -28,41 +28,38 @@ public: enum EState : unsigned char { Normal, - Hover, Pressed, - HoverPressed, Disabled, + Hover, + HoverPressed, Num_States }; -private: - // icon textures are assumed to be square and all with the same size in pixels, no internal check is done - GLTexture m_icon_textures[Num_States]; + struct Data + { + std::string name; + std::string tooltip; + unsigned int sprite_id; + bool is_toggable; + PerlCallback* action_callback; + + Data(); + }; +private: EType m_type; EState m_state; - - std::string m_name; - std::string m_tooltip; - - bool m_is_toggable; - PerlCallback* m_action_callback; + Data m_data; public: - GLToolbarItem(EType type, const std::string& name, const std::string& tooltip, bool is_toggable, PerlCallback* action_callback); - - bool load_textures(const std::string* filenames); + GLToolbarItem(EType type, const Data& data); EState get_state() const; void set_state(EState state); const std::string& get_name() const; - const std::string& get_tooltip() const; - unsigned int get_icon_texture_id() const; - int get_icon_textures_size() const; - void do_action(); bool is_enabled() const; @@ -71,18 +68,48 @@ public: bool is_toggable() const; bool is_separator() const; + + void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int texture_size, unsigned int border_size, unsigned int icon_size, unsigned int gap_size) const; + +private: + GLTexture::Quad_UVs _get_uvs(unsigned int texture_size, unsigned int border_size, unsigned int icon_size, unsigned int gap_size) const; }; class GLToolbar { public: - struct ItemCreationData + // items icon textures are assumed to be square and all with the same size in pixels, no internal check is done + // icons are layed-out into the texture starting from the top-left corner in the same order as enum GLToolbarItem::EState + // from left to right + struct ItemsIconsTexture { - std::string name; - std::string tooltip; - bool is_toggable; - PerlCallback* action_callback; - std::string textures[GLToolbarItem::Num_States]; + GLTexture texture; + // size of the square icons, in pixels + unsigned int items_icon_size; + // distance from the border, in pixels + unsigned int items_icon_border_size; + // distance between two adjacent icons (to avoid filtering artifacts), in pixels + unsigned int items_icon_gap_size; + + ItemsIconsTexture(); + }; + + struct Layout + { + enum Type : unsigned char + { + Horizontal, + Vertical, + Num_Types + }; + + Type type; + float top; + float left; + float separator_size; + float gap_size; + + Layout(); }; private: @@ -90,27 +117,32 @@ private: GLCanvas3D& m_parent; bool m_enabled; - ItemsList m_items; + ItemsIconsTexture m_icons_texture; + Layout m_layout; - float m_textures_scale; - float m_offset_y; - float m_gap_x; - float m_separator_x; + ItemsList m_items; public: explicit GLToolbar(GLCanvas3D& parent); + bool init(const std::string& icons_texture_filename, unsigned int items_icon_size, unsigned int items_icon_border_size, unsigned int items_icon_gap_size); + + Layout::Type get_layout_type() const; + void set_layout_type(Layout::Type type); + + void set_position(float top, float left); + void set_separator_size(float size); + void set_gap_size(float size); + bool is_enabled() const; void set_enabled(bool enable); - void set_textures_scale(float scale); - void set_offset_y(float offset); - void set_gap_x(float gap); - void set_separator_x(float separator); - - bool add_item(const ItemCreationData& data); + bool add_item(const GLToolbarItem::Data& data); bool add_separator(); + float get_width() const; + float get_height() const; + void enable_item(const std::string& name); void disable_item(const std::string& name); @@ -123,10 +155,20 @@ public: void do_action(unsigned int item_id); - void render(const Pointf& mouse_pos) const; + void render() const; private: - float _get_total_width() const; + float _get_width_horizontal() const; + float _get_width_vertical() const; + float _get_height_horizontal() const; + float _get_height_vertical() const; + float _get_main_size() const; + void _update_hover_state_horizontal(const Pointf& mouse_pos); + void _update_hover_state_vertical(const Pointf& mouse_pos); + int _contains_mouse_horizontal(const Pointf& mouse_pos) const; + int _contains_mouse_vertical(const Pointf& mouse_pos) const; + void _render_horizontal() const; + void _render_vertical() const; }; } // namespace GUI |