mirror of
https://github.com/FULU-Foundation/OrcaSlicer-bambulab.git
synced 2026-06-06 13:53:05 -04:00
1. Old mode, as it was always. 2. New mode, when Settings Tabs are hidden on the Plater. Use "cog" icon for the switching to the settings tabs 3. Dlg mode, when Settings Tabs are extracted to the Settings dialog. Use "cog" icon for Show or Focus the Settings Dialog The "Collapse sidebar" toolbar appearance is set in the Preferences.
1471 lines
47 KiB
C++
1471 lines
47 KiB
C++
#include "libslic3r/Point.hpp"
|
|
#include "libslic3r/libslic3r.h"
|
|
|
|
#include "GLToolbar.hpp"
|
|
|
|
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
|
#include "slic3r/GUI/GUI_App.hpp"
|
|
#include "slic3r/GUI/Camera.hpp"
|
|
#else
|
|
#include "../../slic3r/GUI/GLCanvas3D.hpp"
|
|
#include "../../slic3r/GUI/Camera.hpp"
|
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
|
|
#include <wx/event.h>
|
|
#include <wx/bitmap.h>
|
|
#include <wx/dcmemory.h>
|
|
#include <wx/settings.h>
|
|
#include <wx/glcanvas.h>
|
|
|
|
namespace Slic3r {
|
|
namespace GUI {
|
|
|
|
wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
|
|
wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
|
|
wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent);
|
|
wxDEFINE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent);
|
|
wxDEFINE_EVENT(EVT_GLTOOLBAR_COPY, SimpleEvent);
|
|
wxDEFINE_EVENT(EVT_GLTOOLBAR_PASTE, SimpleEvent);
|
|
wxDEFINE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent);
|
|
wxDEFINE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent);
|
|
wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent);
|
|
wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_VOLUMES, SimpleEvent);
|
|
wxDEFINE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent);
|
|
|
|
wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_3D, SimpleEvent);
|
|
wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
|
|
|
|
const GLToolbarItem::ActionCallback GLToolbarItem::Default_Action_Callback = [](){};
|
|
const GLToolbarItem::VisibilityCallback GLToolbarItem::Default_Visibility_Callback = []()->bool { return true; };
|
|
const GLToolbarItem::EnablingCallback GLToolbarItem::Default_Enabling_Callback = []()->bool { return true; };
|
|
const GLToolbarItem::RenderCallback GLToolbarItem::Default_Render_Callback = [](float, float, float, float){};
|
|
|
|
GLToolbarItem::Data::Option::Option()
|
|
: toggable(false)
|
|
, action_callback(Default_Action_Callback)
|
|
, render_callback(nullptr)
|
|
{
|
|
}
|
|
|
|
GLToolbarItem::Data::Data()
|
|
: name("")
|
|
, icon_filename("")
|
|
, tooltip("")
|
|
, additional_tooltip("")
|
|
, sprite_id(-1)
|
|
, visible(true)
|
|
, visibility_callback(Default_Visibility_Callback)
|
|
, enabling_callback(Default_Enabling_Callback)
|
|
{
|
|
}
|
|
|
|
GLToolbarItem::GLToolbarItem(GLToolbarItem::EType type, const GLToolbarItem::Data& data)
|
|
: m_type(type)
|
|
, m_state(Normal)
|
|
, m_data(data)
|
|
, m_last_action_type(Undefined)
|
|
{
|
|
}
|
|
|
|
bool GLToolbarItem::update_visibility()
|
|
{
|
|
bool visible = m_data.visibility_callback();
|
|
bool ret = (m_data.visible != visible);
|
|
if (ret)
|
|
m_data.visible = visible;
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool GLToolbarItem::update_enabled_state()
|
|
{
|
|
bool enabled = m_data.enabling_callback();
|
|
bool ret = (is_enabled() != enabled);
|
|
if (ret)
|
|
m_state = enabled ? GLToolbarItem::Normal : GLToolbarItem::Disabled;
|
|
|
|
return ret;
|
|
}
|
|
|
|
void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const
|
|
{
|
|
auto uvs = [this](unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) -> GLTexture::Quad_UVs
|
|
{
|
|
assert((tex_width != 0) && (tex_height != 0));
|
|
GLTexture::Quad_UVs ret;
|
|
// tiles in the texture are spaced by 1 pixel
|
|
float icon_size_px = (float)(tex_width - 1) / (float)Num_States;
|
|
float inv_tex_width = 1.0f / (float)tex_width;
|
|
float inv_tex_height = 1.0f / (float)tex_height;
|
|
// tiles in the texture are spaced by 1 pixel
|
|
float u_offset = 1.0f * inv_tex_width;
|
|
float v_offset = 1.0f * inv_tex_height;
|
|
float du = icon_size_px * inv_tex_width;
|
|
float dv = icon_size_px * inv_tex_height;
|
|
float left = u_offset + (float)m_state * du;
|
|
float right = left + du - u_offset;
|
|
float top = v_offset + (float)m_data.sprite_id * dv;
|
|
float bottom = top + dv - v_offset;
|
|
ret.left_top = { left, top };
|
|
ret.left_bottom = { left, bottom };
|
|
ret.right_bottom = { right, bottom };
|
|
ret.right_top = { right, top };
|
|
return ret;
|
|
};
|
|
|
|
GLTexture::render_sub_texture(tex_id, left, right, bottom, top, uvs(tex_width, tex_height, icon_size));
|
|
|
|
if (is_pressed())
|
|
{
|
|
if ((m_last_action_type == Left) && m_data.left.can_render())
|
|
m_data.left.render_callback(left, right, bottom, top);
|
|
else if ((m_last_action_type == Right) && m_data.right.can_render())
|
|
m_data.right.render_callback(left, right, bottom, top);
|
|
}
|
|
}
|
|
|
|
BackgroundTexture::Metadata::Metadata()
|
|
: filename("")
|
|
, left(0)
|
|
, right(0)
|
|
, top(0)
|
|
, bottom(0)
|
|
{
|
|
}
|
|
|
|
const float GLToolbar::Default_Icons_Size = 40.0f;
|
|
|
|
GLToolbar::Layout::Layout()
|
|
: type(Horizontal)
|
|
, horizontal_orientation(HO_Center)
|
|
, vertical_orientation(VO_Center)
|
|
, top(0.0f)
|
|
, left(0.0f)
|
|
, border(0.0f)
|
|
, separator_size(0.0f)
|
|
, gap_size(0.0f)
|
|
, icons_size(Default_Icons_Size)
|
|
, scale(1.0f)
|
|
, width(0.0f)
|
|
, height(0.0f)
|
|
, dirty(true)
|
|
{
|
|
}
|
|
|
|
GLToolbar::GLToolbar(GLToolbar::EType type, const std::string& name)
|
|
: m_type(type)
|
|
, m_name(name)
|
|
, m_enabled(false)
|
|
, m_icons_texture_dirty(true)
|
|
#if !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
, m_tooltip("")
|
|
#endif // !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
, m_pressed_toggable_id(-1)
|
|
{
|
|
}
|
|
|
|
GLToolbar::~GLToolbar()
|
|
{
|
|
for (GLToolbarItem* item : m_items)
|
|
{
|
|
delete item;
|
|
}
|
|
}
|
|
|
|
bool GLToolbar::init(const BackgroundTexture::Metadata& background_texture)
|
|
{
|
|
if (m_background_texture.texture.get_id() != 0)
|
|
return true;
|
|
|
|
std::string path = resources_dir() + "/icons/";
|
|
bool res = false;
|
|
|
|
if (!background_texture.filename.empty())
|
|
res = m_background_texture.texture.load_from_file(path + background_texture.filename, false, GLTexture::SingleThreaded, false);
|
|
|
|
if (res)
|
|
m_background_texture.metadata = background_texture;
|
|
|
|
return res;
|
|
}
|
|
|
|
GLToolbar::Layout::EType GLToolbar::get_layout_type() const
|
|
{
|
|
return m_layout.type;
|
|
}
|
|
|
|
void GLToolbar::set_layout_type(GLToolbar::Layout::EType type)
|
|
{
|
|
m_layout.type = type;
|
|
m_layout.dirty = true;
|
|
}
|
|
|
|
void GLToolbar::set_position(float top, float left)
|
|
{
|
|
m_layout.top = top;
|
|
m_layout.left = left;
|
|
}
|
|
|
|
void GLToolbar::set_border(float border)
|
|
{
|
|
m_layout.border = border;
|
|
m_layout.dirty = true;
|
|
}
|
|
|
|
void GLToolbar::set_separator_size(float size)
|
|
{
|
|
m_layout.separator_size = size;
|
|
m_layout.dirty = true;
|
|
}
|
|
|
|
void GLToolbar::set_gap_size(float size)
|
|
{
|
|
m_layout.gap_size = size;
|
|
m_layout.dirty = true;
|
|
}
|
|
|
|
void GLToolbar::set_icons_size(float size)
|
|
{
|
|
if (m_layout.icons_size != size)
|
|
{
|
|
m_layout.icons_size = size;
|
|
m_layout.dirty = true;
|
|
m_icons_texture_dirty = true;
|
|
}
|
|
}
|
|
|
|
void GLToolbar::set_scale(float scale)
|
|
{
|
|
if (m_layout.scale != scale)
|
|
{
|
|
m_layout.scale = scale;
|
|
m_layout.dirty = true;
|
|
m_icons_texture_dirty = true;
|
|
}
|
|
}
|
|
|
|
bool GLToolbar::is_enabled() const
|
|
{
|
|
return m_enabled;
|
|
}
|
|
|
|
void GLToolbar::set_enabled(bool enable)
|
|
{
|
|
m_enabled = enable;//true; etFIXME
|
|
}
|
|
|
|
bool GLToolbar::add_item(const GLToolbarItem::Data& data)
|
|
{
|
|
GLToolbarItem* item = new GLToolbarItem(GLToolbarItem::Action, data);
|
|
if (item == nullptr)
|
|
return false;
|
|
|
|
m_items.push_back(item);
|
|
m_layout.dirty = true;
|
|
return true;
|
|
}
|
|
|
|
bool GLToolbar::add_separator()
|
|
{
|
|
GLToolbarItem::Data data;
|
|
GLToolbarItem* item = new GLToolbarItem(GLToolbarItem::Separator, data);
|
|
if (item == nullptr)
|
|
return false;
|
|
|
|
m_items.push_back(item);
|
|
m_layout.dirty = true;
|
|
return true;
|
|
}
|
|
|
|
float GLToolbar::get_width() const
|
|
{
|
|
if (m_layout.dirty)
|
|
calc_layout();
|
|
|
|
return m_layout.width;
|
|
}
|
|
|
|
float GLToolbar::get_height() const
|
|
{
|
|
if (m_layout.dirty)
|
|
calc_layout();
|
|
|
|
return m_layout.height;
|
|
}
|
|
|
|
void GLToolbar::select_item(const std::string& name)
|
|
{
|
|
if (is_item_disabled(name))
|
|
return;
|
|
|
|
for (GLToolbarItem* item : m_items)
|
|
{
|
|
if (!item->is_disabled())
|
|
{
|
|
bool hover = item->is_hovered();
|
|
item->set_state((item->get_name() == name) ? (hover ? GLToolbarItem::HoverPressed : GLToolbarItem::Pressed) : (hover ? GLToolbarItem::Hover : GLToolbarItem::Normal));
|
|
}
|
|
}
|
|
}
|
|
|
|
bool GLToolbar::is_item_pressed(const std::string& name) const
|
|
{
|
|
for (const GLToolbarItem* item : m_items)
|
|
{
|
|
if (item->get_name() == name)
|
|
return item->is_pressed();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool GLToolbar::is_item_disabled(const std::string& name) const
|
|
{
|
|
for (const GLToolbarItem* item : m_items)
|
|
{
|
|
if (item->get_name() == name)
|
|
return item->is_disabled();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool GLToolbar::is_item_visible(const std::string& name) const
|
|
{
|
|
for (const GLToolbarItem* item : m_items)
|
|
{
|
|
if (item->get_name() == name)
|
|
return item->is_visible();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool GLToolbar::is_any_item_pressed() const
|
|
{
|
|
for (const GLToolbarItem* item : m_items)
|
|
{
|
|
if (item->is_pressed())
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int GLToolbar::get_item_id(const std::string& name) const
|
|
{
|
|
for (int i = 0; i < (int)m_items.size(); ++i)
|
|
{
|
|
if (m_items[i]->get_name() == name)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
std::string GLToolbar::get_tooltip() const
|
|
{
|
|
std::string tooltip;
|
|
|
|
for (GLToolbarItem* item : m_items)
|
|
{
|
|
if (item->is_hovered())
|
|
{
|
|
tooltip = item->get_tooltip();
|
|
if (!item->is_pressed())
|
|
{
|
|
const std::string& additional_tooltip = item->get_additional_tooltip();
|
|
if (!additional_tooltip.empty())
|
|
tooltip += "\n" + additional_tooltip;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return tooltip;
|
|
}
|
|
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
|
|
void GLToolbar::get_additional_tooltip(int item_id, std::string& text)
|
|
{
|
|
if (0 <= item_id && item_id < (int)m_items.size())
|
|
{
|
|
text = m_items[item_id]->get_additional_tooltip();
|
|
return;
|
|
}
|
|
|
|
text.clear();
|
|
}
|
|
|
|
void GLToolbar::set_additional_tooltip(int item_id, const std::string& text)
|
|
{
|
|
if (0 <= item_id && item_id < (int)m_items.size())
|
|
m_items[item_id]->set_additional_tooltip(text);
|
|
}
|
|
|
|
void GLToolbar::set_tooltip(int item_id, const std::string& text)
|
|
{
|
|
if (0 <= item_id && item_id < (int)m_items.size())
|
|
m_items[item_id]->set_tooltip(text);
|
|
}
|
|
|
|
bool GLToolbar::update_items_state()
|
|
{
|
|
bool ret = false;
|
|
ret |= update_items_visibility();
|
|
ret |= update_items_enabled_state();
|
|
if (!is_any_item_pressed())
|
|
m_pressed_toggable_id = -1;
|
|
|
|
return ret;
|
|
}
|
|
|
|
void GLToolbar::render(const GLCanvas3D& parent) const
|
|
{
|
|
if (!m_enabled || m_items.empty())
|
|
return;
|
|
|
|
if (m_icons_texture_dirty)
|
|
generate_icons_texture();
|
|
|
|
switch (m_layout.type)
|
|
{
|
|
default:
|
|
case Layout::Horizontal: { render_horizontal(parent); break; }
|
|
case Layout::Vertical: { render_vertical(parent); break; }
|
|
}
|
|
}
|
|
|
|
bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
|
|
{
|
|
if (!m_enabled)
|
|
return false;
|
|
|
|
Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY());
|
|
bool processed = false;
|
|
|
|
// mouse anywhere
|
|
if (!evt.Dragging() && !evt.Leaving() && !evt.Entering() && (m_mouse_capture.parent != nullptr))
|
|
{
|
|
if (m_mouse_capture.any() && (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())) {
|
|
// prevents loosing selection into the scene if mouse down was done inside the toolbar and mouse up was down outside it,
|
|
// as when switching between views
|
|
m_mouse_capture.reset();
|
|
#if !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
if (contains_mouse(mouse_pos, parent) == -1)
|
|
// mouse is outside the toolbar
|
|
m_tooltip.clear();
|
|
#endif // !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
return true;
|
|
}
|
|
m_mouse_capture.reset();
|
|
}
|
|
|
|
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
if (evt.Moving())
|
|
update_hover_state(mouse_pos, parent);
|
|
else if (evt.LeftUp())
|
|
{
|
|
if (m_mouse_capture.left)
|
|
{
|
|
processed = true;
|
|
m_mouse_capture.left = false;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
else if (evt.MiddleUp())
|
|
{
|
|
if (m_mouse_capture.middle)
|
|
{
|
|
processed = true;
|
|
m_mouse_capture.middle = false;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
else if (evt.RightUp())
|
|
{
|
|
if (m_mouse_capture.right)
|
|
{
|
|
processed = true;
|
|
m_mouse_capture.right = false;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
else if (evt.Dragging())
|
|
{
|
|
if (m_mouse_capture.any())
|
|
// if the button down was done on this toolbar, prevent from dragging into the scene
|
|
processed = true;
|
|
else
|
|
return false;
|
|
}
|
|
#else
|
|
if (evt.Moving())
|
|
m_tooltip = update_hover_state(mouse_pos, parent);
|
|
else if (evt.LeftUp())
|
|
m_mouse_capture.left = false;
|
|
else if (evt.MiddleUp())
|
|
m_mouse_capture.middle = false;
|
|
else if (evt.RightUp())
|
|
m_mouse_capture.right = false;
|
|
else if (evt.Dragging() && m_mouse_capture.any())
|
|
// if the button down was done on this toolbar, prevent from dragging into the scene
|
|
processed = true;
|
|
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
|
|
int item_id = contains_mouse(mouse_pos, parent);
|
|
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
if (item_id != -1)
|
|
#else
|
|
if (item_id == -1)
|
|
{
|
|
// mouse is outside the toolbar
|
|
m_tooltip.clear();
|
|
}
|
|
else
|
|
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
{
|
|
// mouse inside toolbar
|
|
if (evt.LeftDown() || evt.LeftDClick())
|
|
{
|
|
m_mouse_capture.left = true;
|
|
m_mouse_capture.parent = &parent;
|
|
processed = true;
|
|
if ((item_id != -2) && !m_items[item_id]->is_separator() && ((m_pressed_toggable_id == -1) || (m_items[item_id]->get_last_action_type() == GLToolbarItem::Left)))
|
|
{
|
|
// mouse is inside an icon
|
|
do_action(GLToolbarItem::Left, item_id, parent, true);
|
|
parent.set_as_dirty();
|
|
}
|
|
}
|
|
else if (evt.MiddleDown())
|
|
{
|
|
m_mouse_capture.middle = true;
|
|
m_mouse_capture.parent = &parent;
|
|
}
|
|
else if (evt.RightDown())
|
|
{
|
|
m_mouse_capture.right = true;
|
|
m_mouse_capture.parent = &parent;
|
|
processed = true;
|
|
if ((item_id != -2) && !m_items[item_id]->is_separator() && ((m_pressed_toggable_id == -1) || (m_items[item_id]->get_last_action_type() == GLToolbarItem::Right)))
|
|
{
|
|
// mouse is inside an icon
|
|
do_action(GLToolbarItem::Right, item_id, parent, true);
|
|
parent.set_as_dirty();
|
|
}
|
|
}
|
|
#if !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
else if (evt.LeftUp())
|
|
processed = true;
|
|
#endif // !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
}
|
|
|
|
return processed;
|
|
}
|
|
|
|
void GLToolbar::calc_layout() const
|
|
{
|
|
switch (m_layout.type)
|
|
{
|
|
default:
|
|
case Layout::Horizontal:
|
|
{
|
|
m_layout.width = get_width_horizontal();
|
|
m_layout.height = get_height_horizontal();
|
|
break;
|
|
}
|
|
case Layout::Vertical:
|
|
{
|
|
m_layout.width = get_width_vertical();
|
|
m_layout.height = get_height_vertical();
|
|
break;
|
|
}
|
|
}
|
|
|
|
m_layout.dirty = false;
|
|
}
|
|
|
|
float GLToolbar::get_width_horizontal() const
|
|
{
|
|
return get_main_size();
|
|
}
|
|
|
|
float GLToolbar::get_width_vertical() const
|
|
{
|
|
return (2.0f * m_layout.border + m_layout.icons_size) * m_layout.scale;
|
|
}
|
|
|
|
float GLToolbar::get_height_horizontal() const
|
|
{
|
|
return (2.0f * m_layout.border + m_layout.icons_size) * m_layout.scale;
|
|
}
|
|
|
|
float GLToolbar::get_height_vertical() const
|
|
{
|
|
return get_main_size();
|
|
}
|
|
|
|
float GLToolbar::get_main_size() const
|
|
{
|
|
float size = 2.0f * m_layout.border;
|
|
for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i)
|
|
{
|
|
if (!m_items[i]->is_visible())
|
|
continue;
|
|
|
|
if (m_items[i]->is_separator())
|
|
size += m_layout.separator_size;
|
|
else
|
|
size += (float)m_layout.icons_size;
|
|
}
|
|
|
|
if (m_items.size() > 1)
|
|
size += ((float)m_items.size() - 1.0f) * m_layout.gap_size;
|
|
|
|
return size * m_layout.scale;
|
|
}
|
|
|
|
void GLToolbar::do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas3D& parent, bool check_hover)
|
|
{
|
|
if ((m_pressed_toggable_id == -1) || (m_pressed_toggable_id == item_id))
|
|
{
|
|
if ((0 <= item_id) && (item_id < (int)m_items.size()))
|
|
{
|
|
GLToolbarItem* item = m_items[item_id];
|
|
if ((item != nullptr) && !item->is_separator() && (!check_hover || item->is_hovered()))
|
|
{
|
|
if (((type == GLToolbarItem::Right) && item->is_right_toggable()) ||
|
|
((type == GLToolbarItem::Left) && item->is_left_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);
|
|
else if (state == GLToolbarItem::Pressed)
|
|
item->set_state(GLToolbarItem::Normal);
|
|
else if (state == GLToolbarItem::Normal)
|
|
item->set_state(GLToolbarItem::Pressed);
|
|
|
|
m_pressed_toggable_id = item->is_pressed() ? item_id : -1;
|
|
item->reset_last_action_type();
|
|
|
|
parent.render();
|
|
switch (type)
|
|
{
|
|
default:
|
|
case GLToolbarItem::Left: { item->do_left_action(); break; }
|
|
case GLToolbarItem::Right: { item->do_right_action(); break; }
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_type == Radio)
|
|
select_item(item->get_name());
|
|
else
|
|
item->set_state(item->is_hovered() ? GLToolbarItem::HoverPressed : GLToolbarItem::Pressed);
|
|
|
|
item->reset_last_action_type();
|
|
parent.render();
|
|
switch (type)
|
|
{
|
|
default:
|
|
case GLToolbarItem::Left: { item->do_left_action(); break; }
|
|
case GLToolbarItem::Right: { item->do_right_action(); break; }
|
|
}
|
|
|
|
if ((m_type == Normal) && (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);
|
|
parent.render();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
void GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
|
|
{
|
|
if (!m_enabled)
|
|
return;
|
|
|
|
switch (m_layout.type)
|
|
{
|
|
default:
|
|
case Layout::Horizontal: { update_hover_state_horizontal(mouse_pos, parent); break; }
|
|
case Layout::Vertical: { update_hover_state_vertical(mouse_pos, parent); break; }
|
|
}
|
|
}
|
|
#else
|
|
std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
|
|
{
|
|
if (!m_enabled)
|
|
return "";
|
|
|
|
switch (m_layout.type)
|
|
{
|
|
default:
|
|
case Layout::Horizontal: { return update_hover_state_horizontal(mouse_pos, parent); }
|
|
case Layout::Vertical: { return update_hover_state_vertical(mouse_pos, parent); }
|
|
}
|
|
}
|
|
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
|
|
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
void GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent)
|
|
#else
|
|
std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent)
|
|
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
{
|
|
// NB: mouse_pos is already scaled appropriately
|
|
|
|
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
|
#else
|
|
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float factor = m_layout.scale * inv_zoom;
|
|
|
|
Size cnv_size = parent.get_canvas_size();
|
|
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom);
|
|
|
|
float scaled_icons_size = m_layout.icons_size * factor;
|
|
float scaled_separator_size = m_layout.separator_size * factor;
|
|
float scaled_gap_size = m_layout.gap_size * factor;
|
|
float scaled_border = m_layout.border * factor;
|
|
|
|
float separator_stride = scaled_separator_size + scaled_gap_size;
|
|
float icon_stride = scaled_icons_size + scaled_gap_size;
|
|
|
|
float left = m_layout.left + scaled_border;
|
|
float top = m_layout.top - scaled_border;
|
|
|
|
#if !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
std::string tooltip;
|
|
#endif // !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
|
|
for (GLToolbarItem* item : m_items)
|
|
{
|
|
if (!item->is_visible())
|
|
continue;
|
|
|
|
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 <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top);
|
|
#if !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
if (inside)
|
|
{
|
|
tooltip = item->get_tooltip();
|
|
if (!item->is_pressed())
|
|
{
|
|
const std::string& additional_tooltip = item->get_additional_tooltip();
|
|
if (!additional_tooltip.empty())
|
|
tooltip += "\n" + additional_tooltip;
|
|
}
|
|
}
|
|
#endif // !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
|
|
switch (state)
|
|
{
|
|
case GLToolbarItem::Normal:
|
|
{
|
|
if (inside)
|
|
{
|
|
item->set_state(GLToolbarItem::Hover);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GLToolbarItem::Hover:
|
|
{
|
|
if (!inside)
|
|
{
|
|
item->set_state(GLToolbarItem::Normal);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GLToolbarItem::Pressed:
|
|
{
|
|
if (inside)
|
|
{
|
|
item->set_state(GLToolbarItem::HoverPressed);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GLToolbarItem::HoverPressed:
|
|
{
|
|
if (!inside)
|
|
{
|
|
item->set_state(GLToolbarItem::Pressed);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
case GLToolbarItem::Disabled:
|
|
{
|
|
if (inside)
|
|
{
|
|
item->set_state(GLToolbarItem::HoverDisabled);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GLToolbarItem::HoverDisabled:
|
|
{
|
|
if (!inside)
|
|
{
|
|
item->set_state(GLToolbarItem::Disabled);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
#else
|
|
default:
|
|
case GLToolbarItem::Disabled:
|
|
{
|
|
break;
|
|
}
|
|
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
}
|
|
|
|
left += icon_stride;
|
|
}
|
|
}
|
|
|
|
#if !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
return tooltip;
|
|
#endif // !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
}
|
|
|
|
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
void GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent)
|
|
#else
|
|
std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent)
|
|
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
{
|
|
// NB: mouse_pos is already scaled appropriately
|
|
|
|
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
|
#else
|
|
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float factor = m_layout.scale * inv_zoom;
|
|
|
|
Size cnv_size = parent.get_canvas_size();
|
|
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom);
|
|
|
|
float scaled_icons_size = m_layout.icons_size * factor;
|
|
float scaled_separator_size = m_layout.separator_size * factor;
|
|
float scaled_gap_size = m_layout.gap_size * factor;
|
|
float scaled_border = m_layout.border * factor;
|
|
float separator_stride = scaled_separator_size + scaled_gap_size;
|
|
float icon_stride = scaled_icons_size + scaled_gap_size;
|
|
|
|
float left = m_layout.left + scaled_border;
|
|
float top = m_layout.top - scaled_border;
|
|
|
|
#if !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
std::string tooltip;
|
|
#endif // !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
|
|
for (GLToolbarItem* item : m_items)
|
|
{
|
|
if (!item->is_visible())
|
|
continue;
|
|
|
|
if (item->is_separator())
|
|
top -= separator_stride;
|
|
else
|
|
{
|
|
float right = left + scaled_icons_size;
|
|
float bottom = top - scaled_icons_size;
|
|
|
|
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);
|
|
#if !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
if (inside)
|
|
{
|
|
tooltip = item->get_tooltip();
|
|
if (!item->is_pressed())
|
|
{
|
|
const std::string& additional_tooltip = item->get_additional_tooltip();
|
|
if (!additional_tooltip.empty())
|
|
tooltip += "\n" + additional_tooltip;
|
|
}
|
|
}
|
|
#endif // !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
|
|
switch (state)
|
|
{
|
|
case GLToolbarItem::Normal:
|
|
{
|
|
if (inside)
|
|
{
|
|
item->set_state(GLToolbarItem::Hover);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GLToolbarItem::Hover:
|
|
{
|
|
if (!inside)
|
|
{
|
|
item->set_state(GLToolbarItem::Normal);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GLToolbarItem::Pressed:
|
|
{
|
|
if (inside)
|
|
{
|
|
item->set_state(GLToolbarItem::HoverPressed);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GLToolbarItem::HoverPressed:
|
|
{
|
|
if (!inside)
|
|
{
|
|
item->set_state(GLToolbarItem::Pressed);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
case GLToolbarItem::Disabled:
|
|
{
|
|
if (inside)
|
|
{
|
|
item->set_state(GLToolbarItem::HoverDisabled);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
case GLToolbarItem::HoverDisabled:
|
|
{
|
|
if (!inside)
|
|
{
|
|
item->set_state(GLToolbarItem::Disabled);
|
|
parent.set_as_dirty();
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
#else
|
|
default:
|
|
case GLToolbarItem::Disabled:
|
|
{
|
|
break;
|
|
}
|
|
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
}
|
|
|
|
top -= icon_stride;
|
|
}
|
|
}
|
|
|
|
#if !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
return tooltip;
|
|
#endif // !ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
}
|
|
|
|
int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
|
|
{
|
|
if (!m_enabled)
|
|
return -1;
|
|
|
|
switch (m_layout.type)
|
|
{
|
|
default:
|
|
case Layout::Horizontal: { return contains_mouse_horizontal(mouse_pos, parent); }
|
|
case Layout::Vertical: { return contains_mouse_vertical(mouse_pos, parent); }
|
|
}
|
|
}
|
|
|
|
int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
|
|
{
|
|
// NB: mouse_pos is already scaled appropriately
|
|
|
|
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
|
#else
|
|
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float factor = m_layout.scale * inv_zoom;
|
|
|
|
Size cnv_size = parent.get_canvas_size();
|
|
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom);
|
|
|
|
float scaled_icons_size = m_layout.icons_size * factor;
|
|
float scaled_separator_size = m_layout.separator_size * factor;
|
|
float scaled_gap_size = m_layout.gap_size * factor;
|
|
float scaled_border = m_layout.border * factor;
|
|
|
|
float left = m_layout.left + scaled_border;
|
|
float top = m_layout.top - scaled_border;
|
|
|
|
|
|
for (size_t id=0; id<m_items.size(); ++id)
|
|
{
|
|
GLToolbarItem* item = m_items[id];
|
|
|
|
if (!item->is_visible())
|
|
continue;
|
|
|
|
if (item->is_separator())
|
|
{
|
|
float right = left + scaled_separator_size;
|
|
float bottom = top - scaled_icons_size;
|
|
|
|
// mouse inside the separator
|
|
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
|
|
return id;
|
|
|
|
left = right;
|
|
right += scaled_gap_size;
|
|
|
|
if (id < m_items.size() - 1)
|
|
{
|
|
// mouse inside the gap
|
|
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
|
|
return -2;
|
|
}
|
|
|
|
left = right;
|
|
}
|
|
else
|
|
{
|
|
float right = left + scaled_icons_size;
|
|
float bottom = top - scaled_icons_size;
|
|
|
|
// mouse inside the icon
|
|
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
|
|
return id;
|
|
|
|
left = right;
|
|
right += scaled_gap_size;
|
|
|
|
if (id < m_items.size() - 1)
|
|
{
|
|
// mouse inside the gap
|
|
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
|
|
return -2;
|
|
}
|
|
|
|
left = right;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
|
|
{
|
|
// NB: mouse_pos is already scaled appropriately
|
|
|
|
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
|
#else
|
|
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float factor = m_layout.scale * inv_zoom;
|
|
|
|
Size cnv_size = parent.get_canvas_size();
|
|
Vec2d scaled_mouse_pos((mouse_pos(0) - 0.5 * (double)cnv_size.get_width()) * inv_zoom, (0.5 * (double)cnv_size.get_height() - mouse_pos(1)) * inv_zoom);
|
|
|
|
float scaled_icons_size = m_layout.icons_size * factor;
|
|
float scaled_separator_size = m_layout.separator_size * factor;
|
|
float scaled_gap_size = m_layout.gap_size * factor;
|
|
float scaled_border = m_layout.border * factor;
|
|
|
|
float left = m_layout.left + scaled_border;
|
|
float top = m_layout.top - scaled_border;
|
|
|
|
for (size_t id=0; id<m_items.size(); ++id)
|
|
{
|
|
GLToolbarItem* item = m_items[id];
|
|
|
|
if (!item->is_visible())
|
|
continue;
|
|
|
|
if (item->is_separator())
|
|
{
|
|
float right = left + scaled_icons_size;
|
|
float bottom = top - scaled_separator_size;
|
|
|
|
// mouse inside the separator
|
|
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
|
|
return id;
|
|
|
|
top = bottom;
|
|
bottom -= scaled_gap_size;
|
|
|
|
if (id < m_items.size() - 1)
|
|
{
|
|
// mouse inside the gap
|
|
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
|
|
return -2;
|
|
}
|
|
|
|
top = bottom;
|
|
}
|
|
else
|
|
{
|
|
float right = left + scaled_icons_size;
|
|
float bottom = top - scaled_icons_size;
|
|
|
|
// mouse inside the icon
|
|
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
|
|
return id;
|
|
|
|
top = bottom;
|
|
bottom -= scaled_gap_size;
|
|
|
|
if (id < m_items.size() - 1)
|
|
{
|
|
// mouse inside the gap
|
|
if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
|
|
return -2;
|
|
}
|
|
|
|
top = bottom;
|
|
}
|
|
}
|
|
|
|
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
|
|
{
|
|
unsigned int tex_id = m_icons_texture.get_id();
|
|
int tex_width = m_icons_texture.get_width();
|
|
int tex_height = m_icons_texture.get_height();
|
|
|
|
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
|
#else
|
|
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float factor = inv_zoom * m_layout.scale;
|
|
|
|
float scaled_icons_size = m_layout.icons_size * factor;
|
|
float scaled_separator_size = m_layout.separator_size * factor;
|
|
float scaled_gap_size = m_layout.gap_size * factor;
|
|
float scaled_border = m_layout.border * factor;
|
|
float scaled_width = get_width() * inv_zoom;
|
|
float scaled_height = get_height() * 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;
|
|
float right = left + scaled_width;
|
|
float bottom = top - scaled_height;
|
|
|
|
render_background(left, top, right, bottom, scaled_border);
|
|
|
|
left += scaled_border;
|
|
top -= scaled_border;
|
|
|
|
if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0))
|
|
return;
|
|
|
|
// renders icons
|
|
for (const GLToolbarItem* item : m_items)
|
|
{
|
|
if (!item->is_visible())
|
|
continue;
|
|
|
|
if (item->is_separator())
|
|
left += separator_stride;
|
|
else
|
|
{
|
|
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale));
|
|
left += icon_stride;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GLToolbar::render_vertical(const GLCanvas3D& parent) const
|
|
{
|
|
unsigned int tex_id = m_icons_texture.get_id();
|
|
int tex_width = m_icons_texture.get_width();
|
|
int tex_height = m_icons_texture.get_height();
|
|
|
|
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
|
|
#else
|
|
float inv_zoom = (float)parent.get_camera().get_inv_zoom();
|
|
#endif // ENABLE_NON_STATIC_CANVAS_MANAGER
|
|
float factor = inv_zoom * m_layout.scale;
|
|
|
|
float scaled_icons_size = m_layout.icons_size * factor;
|
|
float scaled_separator_size = m_layout.separator_size * factor;
|
|
float scaled_gap_size = m_layout.gap_size * factor;
|
|
float scaled_border = m_layout.border * factor;
|
|
float scaled_width = get_width() * inv_zoom;
|
|
float scaled_height = get_height() * 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;
|
|
float right = left + scaled_width;
|
|
float bottom = top - scaled_height;
|
|
|
|
render_background(left, top, right, bottom, scaled_border);
|
|
|
|
left += scaled_border;
|
|
top -= scaled_border;
|
|
|
|
if ((tex_id == 0) || (tex_width <= 0) || (tex_height <= 0))
|
|
return;
|
|
|
|
// renders icons
|
|
for (const GLToolbarItem* item : m_items)
|
|
{
|
|
if (!item->is_visible())
|
|
continue;
|
|
|
|
if (item->is_separator())
|
|
top -= separator_stride;
|
|
else
|
|
{
|
|
item->render(tex_id, left, left + scaled_icons_size, top - scaled_icons_size, top, (unsigned int)tex_width, (unsigned int)tex_height, (unsigned int)(m_layout.icons_size * m_layout.scale));
|
|
top -= icon_stride;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool GLToolbar::generate_icons_texture() const
|
|
{
|
|
std::string path = resources_dir() + "/icons/";
|
|
std::vector<std::string> filenames;
|
|
for (GLToolbarItem* item : m_items)
|
|
{
|
|
const std::string& icon_filename = item->get_icon_filename();
|
|
if (!icon_filename.empty())
|
|
filenames.push_back(path + icon_filename);
|
|
}
|
|
|
|
std::vector<std::pair<int, bool>> states;
|
|
if (m_name == "Top")
|
|
{
|
|
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
states.push_back({ 1, false }); // Normal
|
|
states.push_back({ 0, false }); // Pressed
|
|
states.push_back({ 2, false }); // Disabled
|
|
states.push_back({ 0, false }); // Hover
|
|
states.push_back({ 0, false }); // HoverPressed
|
|
states.push_back({ 2, false }); // HoverDisabled
|
|
#else
|
|
states.push_back(std::make_pair(1, false));
|
|
states.push_back(std::make_pair(0, false));
|
|
states.push_back(std::make_pair(2, false));
|
|
states.push_back(std::make_pair(0, false));
|
|
states.push_back(std::make_pair(0, false));
|
|
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
}
|
|
else if (m_name == "View")
|
|
{
|
|
#if ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
states.push_back({ 1, false }); // Normal
|
|
states.push_back({ 1, true }); // Pressed
|
|
states.push_back({ 1, false }); // Disabled
|
|
states.push_back({ 0, false }); // Hover
|
|
states.push_back({ 1, true }); // HoverPressed
|
|
states.push_back({ 1, false }); // HoverDisabled
|
|
#else
|
|
states.push_back(std::make_pair(1, false));
|
|
states.push_back(std::make_pair(1, true));
|
|
states.push_back(std::make_pair(1, false));
|
|
states.push_back(std::make_pair(0, false));
|
|
states.push_back(std::make_pair(1, true));
|
|
#endif // ENABLE_CANVAS_TOOLTIP_USING_IMGUI
|
|
}
|
|
|
|
unsigned int sprite_size_px = (unsigned int)(m_layout.icons_size * m_layout.scale);
|
|
// // force even size
|
|
// if (sprite_size_px % 2 != 0)
|
|
// sprite_size_px += 1;
|
|
|
|
bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, states, sprite_size_px, false);
|
|
if (res)
|
|
m_icons_texture_dirty = false;
|
|
|
|
return res;
|
|
}
|
|
|
|
bool GLToolbar::update_items_visibility()
|
|
{
|
|
bool ret = false;
|
|
|
|
for (GLToolbarItem* item : m_items)
|
|
{
|
|
ret |= item->update_visibility();
|
|
}
|
|
|
|
if (ret)
|
|
m_layout.dirty = true;
|
|
|
|
// updates separators visibility to avoid having two of them consecutive
|
|
bool any_item_visible = false;
|
|
for (GLToolbarItem* item : m_items)
|
|
{
|
|
if (!item->is_separator())
|
|
any_item_visible |= item->is_visible();
|
|
else
|
|
{
|
|
item->set_visible(any_item_visible);
|
|
any_item_visible = false;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool GLToolbar::update_items_enabled_state()
|
|
{
|
|
bool ret = false;
|
|
|
|
for (int i = 0; i < (int)m_items.size(); ++i)
|
|
{
|
|
GLToolbarItem* item = m_items[i];
|
|
ret |= item->update_enabled_state();
|
|
if (item->is_enabled() && (m_pressed_toggable_id != -1) && (m_pressed_toggable_id != i))
|
|
{
|
|
ret = true;
|
|
item->set_state(GLToolbarItem::Disabled);
|
|
}
|
|
}
|
|
|
|
if (ret)
|
|
m_layout.dirty = true;
|
|
|
|
return ret;
|
|
}
|
|
|
|
} // namespace GUI
|
|
} // namespace Slic3r
|