Merge branch 'master' into User/Document/Feature_level_units_selection_#7746
This commit is contained in:
@@ -1152,6 +1152,7 @@ SET(FreeCADGui_CPP_SRCS
|
||||
DocumentPyImp.cpp
|
||||
DocumentObserver.cpp
|
||||
DocumentObserverPython.cpp
|
||||
EditableDatumLabel.cpp
|
||||
ExpressionBinding.cpp
|
||||
ExpressionBindingPy.cpp
|
||||
GraphicsViewZoom.cpp
|
||||
@@ -1183,6 +1184,7 @@ SET(FreeCADGui_SRCS
|
||||
DocumentModel.h
|
||||
DocumentObserver.h
|
||||
DocumentObserverPython.h
|
||||
EditableDatumLabel.h
|
||||
ExpressionBinding.h
|
||||
ExpressionBindingPy.h
|
||||
ExpressionCompleter.h
|
||||
|
||||
@@ -23,15 +23,13 @@
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <QEvent>
|
||||
# include <QGridLayout>
|
||||
# include <QSplitter>
|
||||
#endif
|
||||
|
||||
#include "ComboView.h"
|
||||
#include "BitmapFactory.h"
|
||||
#include "Document.h"
|
||||
#include "PropertyView.h"
|
||||
#include "Tree.h"
|
||||
#include "TaskView/TaskView.h"
|
||||
|
||||
|
||||
using namespace Gui;
|
||||
@@ -40,11 +38,8 @@ using namespace Gui::DockWnd;
|
||||
|
||||
/* TRANSLATOR Gui::DockWnd::ComboView */
|
||||
|
||||
ComboView::ComboView(bool showModel, Gui::Document* pcDocument, QWidget *parent)
|
||||
: DockWindow(pcDocument,parent)
|
||||
, oldTabIndex(0)
|
||||
, modelIndex(-1)
|
||||
, taskIndex(-1)
|
||||
ComboView::ComboView(Gui::Document* pcDocument, QWidget *parent)
|
||||
: DockWindow(pcDocument, parent)
|
||||
{
|
||||
setWindowTitle(tr("Combo View"));
|
||||
|
||||
@@ -53,102 +48,20 @@ ComboView::ComboView(bool showModel, Gui::Document* pcDocument, QWidget *parent)
|
||||
pLayout->setContentsMargins ( 0, 0, 0, 0 );
|
||||
|
||||
// tabs to switch between Tree/Properties and TaskPanel
|
||||
tabs = new QTabWidget ();
|
||||
tabs->setObjectName(QString::fromUtf8("combiTab"));
|
||||
tabs->setTabPosition(QTabWidget::North);
|
||||
pLayout->addWidget( tabs, 0, 0 );
|
||||
auto splitter = new QSplitter();
|
||||
pLayout->addWidget( splitter, 0, 0 );
|
||||
|
||||
connect(tabs, qOverload<int>(&QTabWidget::currentChanged),
|
||||
this, &ComboView::onCurrentTabChanged);
|
||||
if (showModel) {
|
||||
// splitter between tree and property view
|
||||
auto splitter = new QSplitter();
|
||||
splitter->setOrientation(Qt::Vertical);
|
||||
// splitter between tree and property view
|
||||
splitter->setOrientation(Qt::Vertical);
|
||||
|
||||
tree = new TreePanel("ComboView", this);
|
||||
splitter->addWidget(tree);
|
||||
tree = new TreePanel("ComboView", this);
|
||||
splitter->addWidget(tree);
|
||||
|
||||
// property view
|
||||
prop = new PropertyView(this);
|
||||
splitter->addWidget(prop);
|
||||
modelIndex = tabs->addTab(splitter,tr("Model"));
|
||||
}
|
||||
else {
|
||||
tree = nullptr;
|
||||
prop = nullptr;
|
||||
}
|
||||
|
||||
// task panel
|
||||
taskPanel = new Gui::TaskView::TaskView(this);
|
||||
taskIndex = tabs->addTab(taskPanel, tr("Tasks"));
|
||||
|
||||
// task panel
|
||||
//projectView = new Gui::ProjectWidget(this);
|
||||
//tabs->addTab(projectView, tr("Project"));
|
||||
// property view
|
||||
prop = new PropertyView(this);
|
||||
splitter->addWidget(prop);
|
||||
}
|
||||
|
||||
ComboView::~ComboView() = default;
|
||||
|
||||
void ComboView::showDialog(Gui::TaskView::TaskDialog *dlg)
|
||||
{
|
||||
static QIcon icon = Gui::BitmapFactory().pixmap("edit-edit.svg");
|
||||
|
||||
// switch to the TaskView tab
|
||||
oldTabIndex = tabs->currentIndex();
|
||||
tabs->setCurrentIndex(taskIndex);
|
||||
tabs->setTabIcon(taskIndex, icon);
|
||||
// set the dialog
|
||||
taskPanel->showDialog(dlg);
|
||||
|
||||
// force to show the combo view
|
||||
if (modelIndex < 0) {
|
||||
if (parentWidget())
|
||||
parentWidget()->raise();
|
||||
}
|
||||
}
|
||||
|
||||
void ComboView::closeDialog()
|
||||
{
|
||||
// close the dialog
|
||||
taskPanel->removeDialog();
|
||||
}
|
||||
|
||||
void ComboView::closedDialog()
|
||||
{
|
||||
static QIcon icon = QIcon();
|
||||
|
||||
// dialog has been closed
|
||||
tabs->setCurrentIndex(oldTabIndex);
|
||||
tabs->setTabIcon(taskIndex, icon);
|
||||
}
|
||||
|
||||
void ComboView::showTreeView()
|
||||
{
|
||||
// switch to the tree view
|
||||
tabs->setCurrentIndex(modelIndex);
|
||||
}
|
||||
|
||||
void ComboView::showTaskView()
|
||||
{
|
||||
// switch to the task view
|
||||
tabs->setCurrentIndex(taskIndex);
|
||||
}
|
||||
|
||||
void ComboView::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
tabs->setTabText(modelIndex, tr("Model"));
|
||||
tabs->setTabText(taskIndex, tr("Tasks"));
|
||||
//tabs->setTabText(2, tr("Project"));
|
||||
}
|
||||
|
||||
DockWindow::changeEvent(e);
|
||||
}
|
||||
|
||||
void ComboView::onCurrentTabChanged(int index)
|
||||
{
|
||||
if (index != taskIndex)
|
||||
oldTabIndex = index;
|
||||
}
|
||||
|
||||
#include "moc_ComboView.cpp"
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Gui {
|
||||
namespace DockWnd {
|
||||
|
||||
/** Combo View
|
||||
* is a combination of a tree, property and TaskPanel for
|
||||
* is a combination of a tree and property view for
|
||||
* integrated user action.
|
||||
*/
|
||||
class GuiExport ComboView : public Gui::DockWindow
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
* A constructor.
|
||||
* A more elaborate description of the constructor.
|
||||
*/
|
||||
ComboView(bool showModel, Gui::Document* pcDocument, QWidget *parent=nullptr);
|
||||
ComboView(Gui::Document* pcDocument, QWidget *parent=nullptr);
|
||||
|
||||
/**
|
||||
* A destructor.
|
||||
@@ -76,33 +76,11 @@ public:
|
||||
*/
|
||||
~ComboView() override;
|
||||
|
||||
Gui::TaskView::TaskView *getTaskPanel(){return taskPanel;}
|
||||
QTabWidget* getTabPanel() const { return tabs;}
|
||||
|
||||
|
||||
friend class Gui::ControlSingleton;
|
||||
|
||||
void showTreeView();
|
||||
void showTaskView();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onCurrentTabChanged(int index);
|
||||
|
||||
protected:
|
||||
void showDialog(Gui::TaskView::TaskDialog *dlg);
|
||||
void closeDialog();
|
||||
void closedDialog();
|
||||
void changeEvent(QEvent *e) override;
|
||||
|
||||
private:
|
||||
int oldTabIndex;
|
||||
int modelIndex;
|
||||
int taskIndex;
|
||||
QTabWidget * tabs;
|
||||
Gui::PropertyView * prop;
|
||||
Gui::TreePanel * tree;
|
||||
Gui::TaskView::TaskView * taskPanel;
|
||||
//Gui::ProjectWidget * projectView;
|
||||
};
|
||||
|
||||
} // namespace DockWnd
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include <Gui/MainWindow.h>
|
||||
|
||||
#include "Control.h"
|
||||
#include "BitmapFactory.h"
|
||||
#include "Tree.h"
|
||||
#include "TaskView/TaskView.h"
|
||||
|
||||
|
||||
@@ -46,10 +48,10 @@ using namespace std;
|
||||
/* TRANSLATOR Gui::ControlSingleton */
|
||||
|
||||
ControlSingleton* ControlSingleton::_pcSingleton = nullptr;
|
||||
static QPointer<Gui::TaskView::TaskView> _taskPanel = nullptr;
|
||||
|
||||
ControlSingleton::ControlSingleton()
|
||||
: ActiveDialog(nullptr)
|
||||
, oldTabIndex(-1)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -58,37 +60,86 @@ ControlSingleton::~ControlSingleton() = default;
|
||||
|
||||
Gui::TaskView::TaskView* ControlSingleton::taskPanel() const
|
||||
{
|
||||
auto pcComboView = qobject_cast<Gui::DockWnd::ComboView*>
|
||||
(Gui::DockWindowManager::instance()->getDockWindow("Combo View"));
|
||||
// should return the pointer to combo view
|
||||
if (pcComboView)
|
||||
return pcComboView->getTaskPanel();
|
||||
// not all workbenches have the combo view enabled
|
||||
else if (_taskPanel)
|
||||
return _taskPanel;
|
||||
// no task panel available
|
||||
else
|
||||
return nullptr;
|
||||
auto taskView = qobject_cast<Gui::TaskView::TaskView*>
|
||||
(Gui::DockWindowManager::instance()->getDockWindow("Tasks"));
|
||||
return taskView;
|
||||
}
|
||||
|
||||
void ControlSingleton::showDockWidget(QWidget* widget)
|
||||
{
|
||||
QWidget* parent = widget->parentWidget();
|
||||
if (parent) {
|
||||
parent->show();
|
||||
parent->raise();
|
||||
}
|
||||
}
|
||||
|
||||
QTabBar* ControlSingleton::findTabBar(QDockWidget* widget) const
|
||||
{
|
||||
int count = getMainWindow()->tabifiedDockWidgets(widget).size() + 1;
|
||||
if (count > 1) {
|
||||
QList<QTabBar*> bars = getMainWindow()->findChildren<QTabBar*>();
|
||||
for (auto it : bars) {
|
||||
if (it->count() <= count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (it->tabText(i) == widget->windowTitle()) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ControlSingleton::aboutToShowDialog(QDockWidget* widget)
|
||||
{
|
||||
static QIcon icon = Gui::BitmapFactory().pixmap("edit-edit.svg");
|
||||
QTabBar* bar = findTabBar(widget);
|
||||
if (bar) {
|
||||
oldTabIndex = bar->currentIndex();
|
||||
for (int i = 0; i < bar->count(); i++) {
|
||||
if (bar->tabText(i) == widget->windowTitle()) {
|
||||
bar->setTabIcon(i, icon);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
widget->show();
|
||||
widget->raise();
|
||||
}
|
||||
|
||||
void ControlSingleton::aboutToHideDialog(QDockWidget* widget)
|
||||
{
|
||||
QTabBar* bar = findTabBar(widget);
|
||||
if (bar) {
|
||||
bar->setCurrentIndex(oldTabIndex);
|
||||
for (int i = 0; i < bar->count(); i++) {
|
||||
if (bar->tabText(i) == widget->windowTitle()) {
|
||||
bar->setTabIcon(i, QIcon());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ControlSingleton::showTaskView()
|
||||
{
|
||||
auto pcComboView = qobject_cast<Gui::DockWnd::ComboView*>
|
||||
(Gui::DockWindowManager::instance()->getDockWindow("Combo View"));
|
||||
if (pcComboView)
|
||||
pcComboView->showTaskView();
|
||||
else if (_taskPanel)
|
||||
_taskPanel->raise();
|
||||
Gui::TaskView::TaskView* taskView = taskPanel();
|
||||
if (taskView) {
|
||||
showDockWidget(taskView);
|
||||
}
|
||||
}
|
||||
|
||||
void ControlSingleton::showModelView()
|
||||
{
|
||||
auto pcComboView = qobject_cast<Gui::DockWnd::ComboView*>
|
||||
(Gui::DockWindowManager::instance()->getDockWindow("Combo View"));
|
||||
if (pcComboView)
|
||||
pcComboView->showTreeView();
|
||||
else if (_taskPanel)
|
||||
_taskPanel->raise();
|
||||
auto treeView = qobject_cast<Gui::TreeDockWidget*>
|
||||
(Gui::DockWindowManager::instance()->getDockWindow("Tree view"));
|
||||
if (treeView) {
|
||||
showDockWidget(treeView);
|
||||
}
|
||||
}
|
||||
|
||||
void ControlSingleton::showDialog(Gui::TaskView::TaskDialog *dlg)
|
||||
@@ -113,14 +164,15 @@ void ControlSingleton::showDialog(Gui::TaskView::TaskDialog *dlg)
|
||||
// which may open a transaction but fails when auto transaction is still active.
|
||||
App::AutoTransaction::setEnable(false);
|
||||
|
||||
auto pcComboView = qobject_cast<Gui::DockWnd::ComboView*>
|
||||
(Gui::DockWindowManager::instance()->getDockWindow("Combo View"));
|
||||
Gui::TaskView::TaskView* taskView = taskPanel();
|
||||
// should return the pointer to combo view
|
||||
if (pcComboView) {
|
||||
pcComboView->showDialog(dlg);
|
||||
if (taskView) {
|
||||
taskView->showDialog(dlg);
|
||||
|
||||
// make sure that the combo view is shown
|
||||
auto dw = qobject_cast<QDockWidget*>(pcComboView->parentWidget());
|
||||
auto dw = qobject_cast<QDockWidget*>(taskView->parentWidget());
|
||||
if (dw) {
|
||||
aboutToShowDialog(dw);
|
||||
dw->setVisible(true);
|
||||
dw->toggleViewAction()->setVisible(true);
|
||||
dw->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable);
|
||||
@@ -132,37 +184,6 @@ void ControlSingleton::showDialog(Gui::TaskView::TaskDialog *dlg)
|
||||
connect(dlg, &TaskView::TaskDialog::aboutToBeDestroyed,
|
||||
this, &ControlSingleton::closedDialog);
|
||||
}
|
||||
// not all workbenches have the combo view enabled
|
||||
else if (!_taskPanel) {
|
||||
auto dw = new QDockWidget();
|
||||
dw->setWindowTitle(tr("Task panel"));
|
||||
dw->setFeatures(QDockWidget::DockWidgetMovable);
|
||||
_taskPanel = new Gui::TaskView::TaskView(dw);
|
||||
dw->setWidget(_taskPanel);
|
||||
_taskPanel->showDialog(dlg);
|
||||
getMainWindow()->addDockWidget(Qt::LeftDockWidgetArea, dw);
|
||||
connect(dlg, &TaskView::TaskDialog::destroyed, dw, &ControlSingleton::deleteLater);
|
||||
|
||||
// if we have the normal tree view available then just tabify with it
|
||||
QWidget* treeView = Gui::DockWindowManager::instance()->getDockWindow("Tree view");
|
||||
QDockWidget* par = treeView ? qobject_cast<QDockWidget*>(treeView->parent()) : 0;
|
||||
if (par && par->isVisible()) {
|
||||
getMainWindow()->tabifyDockWidget(par, dw);
|
||||
qApp->processEvents(); // make sure that the task panel is tabified now
|
||||
dw->show();
|
||||
dw->raise();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QTabWidget* ControlSingleton::tabPanel() const
|
||||
{
|
||||
Gui::DockWnd::ComboView* pcComboView = qobject_cast<Gui::DockWnd::ComboView*>
|
||||
(Gui::DockWindowManager::instance()->getDockWindow("Combo View"));
|
||||
// should return the pointer to combo view
|
||||
if (pcComboView)
|
||||
return pcComboView->getTabPanel();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Gui::TaskView::TaskDialog* ControlSingleton::activeDialog() const
|
||||
@@ -170,22 +191,11 @@ Gui::TaskView::TaskDialog* ControlSingleton::activeDialog() const
|
||||
return ActiveDialog;
|
||||
}
|
||||
|
||||
Gui::TaskView::TaskView* ControlSingleton::getTaskPanel()
|
||||
{
|
||||
// should return the pointer to combo view
|
||||
auto pcComboView = qobject_cast<Gui::DockWnd::ComboView*>
|
||||
(Gui::DockWindowManager::instance()->getDockWindow("Combo View"));
|
||||
if (pcComboView)
|
||||
return pcComboView->getTaskPanel();
|
||||
else
|
||||
return _taskPanel;
|
||||
}
|
||||
|
||||
void ControlSingleton::accept()
|
||||
{
|
||||
Gui::TaskView::TaskView* taskPanel = getTaskPanel();
|
||||
if (taskPanel) {
|
||||
taskPanel->accept();
|
||||
Gui::TaskView::TaskView* taskView = taskPanel();
|
||||
if (taskView) {
|
||||
taskView->accept();
|
||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
|
||||
QEventLoop::ExcludeSocketNotifiers);
|
||||
}
|
||||
@@ -193,9 +203,9 @@ void ControlSingleton::accept()
|
||||
|
||||
void ControlSingleton::reject()
|
||||
{
|
||||
Gui::TaskView::TaskView* taskPanel = getTaskPanel();
|
||||
if (taskPanel) {
|
||||
taskPanel->reject();
|
||||
Gui::TaskView::TaskView* taskView = taskPanel();
|
||||
if (taskView) {
|
||||
taskView->reject();
|
||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
|
||||
QEventLoop::ExcludeSocketNotifiers);
|
||||
}
|
||||
@@ -203,29 +213,25 @@ void ControlSingleton::reject()
|
||||
|
||||
void ControlSingleton::closeDialog()
|
||||
{
|
||||
auto pcComboView = qobject_cast<Gui::DockWnd::ComboView*>
|
||||
(Gui::DockWindowManager::instance()->getDockWindow("Combo View"));
|
||||
// should return the pointer to combo view
|
||||
if (pcComboView)
|
||||
pcComboView->closeDialog();
|
||||
else if (_taskPanel)
|
||||
_taskPanel->removeDialog();
|
||||
Gui::TaskView::TaskView* taskView = taskPanel();
|
||||
if (taskView)
|
||||
taskView->removeDialog();
|
||||
}
|
||||
|
||||
void ControlSingleton::closedDialog()
|
||||
{
|
||||
ActiveDialog = nullptr;
|
||||
auto pcComboView = qobject_cast<Gui::DockWnd::ComboView*>
|
||||
(Gui::DockWindowManager::instance()->getDockWindow("Combo View"));
|
||||
// should return the pointer to combo view
|
||||
assert(pcComboView);
|
||||
pcComboView->closedDialog();
|
||||
Gui::TaskView::TaskView* taskView = taskPanel();
|
||||
assert(taskView);
|
||||
|
||||
// make sure that the combo view is shown
|
||||
auto dw = qobject_cast<QDockWidget*>(pcComboView->parentWidget());
|
||||
if (dw)
|
||||
auto dw = qobject_cast<QDockWidget*>(taskView->parentWidget());
|
||||
if (dw) {
|
||||
aboutToHideDialog(dw);
|
||||
dw->setFeatures(QDockWidget::DockWidgetClosable
|
||||
| QDockWidget::DockWidgetMovable
|
||||
| QDockWidget::DockWidgetFloatable);
|
||||
}
|
||||
}
|
||||
|
||||
bool ControlSingleton::isAllowedAlterDocument() const
|
||||
|
||||
@@ -32,7 +32,8 @@
|
||||
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
|
||||
class QTabWidget;
|
||||
class QDockWidget;
|
||||
class QTabBar;
|
||||
|
||||
namespace App
|
||||
{
|
||||
@@ -75,8 +76,6 @@ public:
|
||||
Gui::TaskView::TaskView* taskPanel() const;
|
||||
/// raising the model view
|
||||
void showModelView();
|
||||
/// get the tab panel
|
||||
QTabWidget* tabPanel() const;
|
||||
//@}
|
||||
|
||||
/*!
|
||||
@@ -106,9 +105,6 @@ private Q_SLOTS:
|
||||
/// This get called by the TaskView when the Dialog is finished
|
||||
void closedDialog();
|
||||
|
||||
private:
|
||||
Gui::TaskView::TaskView *getTaskPanel();
|
||||
|
||||
private:
|
||||
struct status {
|
||||
std::bitset<32> StatusBits;
|
||||
@@ -117,12 +113,17 @@ private:
|
||||
std::stack<status> StatusStack;
|
||||
|
||||
Gui::TaskView::TaskDialog *ActiveDialog;
|
||||
int oldTabIndex;
|
||||
|
||||
private:
|
||||
/// Construction
|
||||
ControlSingleton();
|
||||
/// Destruction
|
||||
~ControlSingleton() override;
|
||||
void showDockWidget(QWidget*);
|
||||
QTabBar* findTabBar(QDockWidget*) const;
|
||||
void aboutToShowDialog(QDockWidget* widget);
|
||||
void aboutToHideDialog(QDockWidget* widget);
|
||||
|
||||
static ControlSingleton* _pcSingleton;
|
||||
};
|
||||
|
||||
@@ -77,7 +77,39 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Find file:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="LineEditFind">
|
||||
<property name="toolTip">
|
||||
<string>Case-insensitive search for filenames, regular expressions supported</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Find in files:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="LineEditFindInFiles">
|
||||
<property name="toolTip">
|
||||
<string>Filter by case-insensitive file content, regular expressions supported</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QTabWidget" name="tabMacroWidget">
|
||||
<property name="tabPosition">
|
||||
<enum>QTabWidget::North</enum>
|
||||
@@ -137,7 +169,7 @@
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
@@ -281,7 +313,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="DestinationGroup">
|
||||
<property name="title">
|
||||
<string>User macros location:</string>
|
||||
@@ -307,15 +339,12 @@
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="mode">
|
||||
<enum>Gui::FileChooser::Directory</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
# include <QMessageBox>
|
||||
# include <QComboBox>
|
||||
# include <QSignalBlocker>
|
||||
# include <QTextStream>
|
||||
#endif
|
||||
|
||||
#include <App/Document.h>
|
||||
@@ -132,35 +133,108 @@ void DlgMacroExecuteImp::setupConnections()
|
||||
this, &DlgMacroExecuteImp::onSystemMacroListBoxCurrentItemChanged);
|
||||
connect(ui->tabMacroWidget, &QTabWidget::currentChanged,
|
||||
this, &DlgMacroExecuteImp::onTabMacroWidgetCurrentChanged);
|
||||
connect(ui->LineEditFind, &QLineEdit::textChanged,
|
||||
this, &DlgMacroExecuteImp::onLineEditFindTextChanged);
|
||||
connect(ui->LineEditFindInFiles, &QLineEdit::textChanged,
|
||||
this, &DlgMacroExecuteImp::onLineEditFindInFilesTextChanged);
|
||||
}
|
||||
|
||||
/** Take a folder and return a StringList of the filenames in it
|
||||
* filtered by both filename *and* by content, if the user has
|
||||
* put text in one or both of the search line edits.
|
||||
*
|
||||
* First filtering is done by file name, which reduces the
|
||||
* number of files to open and read (relatively expensive operation).
|
||||
*
|
||||
* Then we filter by file content after reducing the number of files
|
||||
* to open and read. But both loops are skipped if there is no text
|
||||
* in either of the line edits.
|
||||
*
|
||||
* We do this as another function in order to reuse this code for
|
||||
* doing both the User and System macro list boxes in the fillUpList() function.
|
||||
*/
|
||||
|
||||
QStringList DlgMacroExecuteImp::filterFiles(const QString& folder){
|
||||
QDir dir(folder, QLatin1String("*.FCMacro *.py"));
|
||||
QStringList unfiltered = dir.entryList(); //all .fcmacro and .py files
|
||||
QString fileFilter = ui->LineEditFind->text(); //used to search by filename
|
||||
QString searchText = ui->LineEditFindInFiles->text(); //used to search in file content
|
||||
|
||||
if (fileFilter.isEmpty() && searchText.isEmpty()){ //skip filtering if no filters
|
||||
return unfiltered;
|
||||
}
|
||||
QStringList filteredByFileName;
|
||||
if (fileFilter.isEmpty()){
|
||||
filteredByFileName = unfiltered; //skip the loop if no file filter
|
||||
} else {
|
||||
QRegularExpression regexFileName(fileFilter, QRegularExpression::CaseInsensitiveOption);
|
||||
bool isValidFileFilter = regexFileName.isValid(); //check here instead of inside the loop
|
||||
for (auto uf : unfiltered){
|
||||
if (isValidFileFilter){
|
||||
if (regexFileName.match(uf).hasMatch()) {
|
||||
filteredByFileName.append(uf);
|
||||
}
|
||||
} else { //not valid, so do a simple text search
|
||||
if (uf.contains(fileFilter, Qt::CaseInsensitive)) {
|
||||
filteredByFileName.append(uf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchText.isEmpty()){ //skip reading file contents if no find in file filter
|
||||
return filteredByFileName;
|
||||
}
|
||||
|
||||
QRegularExpression regexContent(searchText, QRegularExpression::CaseInsensitiveOption);
|
||||
bool isValidContentFilter = regexContent.isValid();
|
||||
QStringList filteredByContent;
|
||||
for (auto fn : filteredByFileName) {
|
||||
const QString &fileName = fn;
|
||||
QString filePath = dir.filePath(fileName);
|
||||
QFile file(filePath);
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QTextStream in(&file);
|
||||
QString fileContent = in.readAll();
|
||||
if (isValidContentFilter){
|
||||
if (regexContent.match(fileContent).hasMatch()) {
|
||||
filteredByContent.append(fileName);
|
||||
}
|
||||
} else {
|
||||
if (fileContent.contains(searchText, Qt::CaseInsensitive)){
|
||||
filteredByContent.append(fileName);
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
return filteredByContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills up the list with all macro files found in the specified location.
|
||||
* Fills up the list with macro files found in the specified location
|
||||
* that have been filtered by both filename and by content
|
||||
*/
|
||||
void DlgMacroExecuteImp::fillUpList()
|
||||
{
|
||||
// lists all files in macro path
|
||||
QDir dir(this->macroPath, QLatin1String("*.FCMacro *.py"));
|
||||
|
||||
// fill up with the directory
|
||||
QStringList filteredByContent = this->filterFiles(this->macroPath);
|
||||
ui->userMacroListBox->clear();
|
||||
for (unsigned int i=0; i<dir.count(); i++ ) {
|
||||
for (auto fn : filteredByContent){
|
||||
auto item = new MacroItem(ui->userMacroListBox,false);
|
||||
item->setText(0, dir[i]);
|
||||
item->setText(0, fn);
|
||||
}
|
||||
|
||||
QString dirstr = QString::fromStdString(App::Application::getHomePath()) + QString::fromLatin1("Macro");
|
||||
dir = QDir(dirstr, QLatin1String("*.FCMacro *.py"));
|
||||
filteredByContent = this->filterFiles(dirstr);
|
||||
|
||||
ui->systemMacroListBox->clear();
|
||||
if (dir.exists()) {
|
||||
for (unsigned int i=0; i<dir.count(); i++ ) {
|
||||
auto item = new MacroItem(ui->systemMacroListBox,true);
|
||||
item->setText(0, dir[i]);
|
||||
}
|
||||
for (auto fn : filteredByContent) {
|
||||
auto item = new MacroItem(ui->systemMacroListBox,true);
|
||||
item->setText(0, fn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Selects a macro file in the list view.
|
||||
*/
|
||||
@@ -188,6 +262,16 @@ void DlgMacroExecuteImp::onUserMacroListBoxCurrentItemChanged(QTreeWidgetItem* i
|
||||
}
|
||||
}
|
||||
|
||||
void DlgMacroExecuteImp::onLineEditFindTextChanged(const QString &text){
|
||||
Q_UNUSED(text);
|
||||
this->fillUpList();
|
||||
}
|
||||
|
||||
void DlgMacroExecuteImp::onLineEditFindInFilesTextChanged(const QString &text){
|
||||
Q_UNUSED(text);
|
||||
this->fillUpList();
|
||||
}
|
||||
|
||||
void DlgMacroExecuteImp::onSystemMacroListBoxCurrentItemChanged(QTreeWidgetItem* item)
|
||||
{
|
||||
if (item) {
|
||||
|
||||
@@ -64,9 +64,12 @@ private:
|
||||
void onUserMacroListBoxCurrentItemChanged(QTreeWidgetItem*);
|
||||
void onSystemMacroListBoxCurrentItemChanged(QTreeWidgetItem*);
|
||||
void onTabMacroWidgetCurrentChanged(int index);
|
||||
void onLineEditFindTextChanged(const QString&);
|
||||
void onLineEditFindInFilesTextChanged(const QString&);
|
||||
|
||||
protected:
|
||||
void fillUpList();
|
||||
QStringList filterFiles(const QString&);
|
||||
|
||||
protected:
|
||||
QString macroPath;
|
||||
|
||||
@@ -175,6 +175,20 @@ QWidget* DockWindowManager::getDockWindow(const char* name) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dock widget by name.
|
||||
* If it does not exist 0 is returned.
|
||||
*/
|
||||
QDockWidget* DockWindowManager::getDockContainer(const char* name) const
|
||||
{
|
||||
for (QList<QDockWidget*>::Iterator it = d->_dockedWindows.begin(); it != d->_dockedWindows.end(); ++it) {
|
||||
if ((*it)->objectName() == QLatin1String(name))
|
||||
return (*it);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all widgets inside the dock windows.
|
||||
*/
|
||||
|
||||
@@ -86,6 +86,8 @@ public:
|
||||
/// returned from @ref addDockWindow. If you want to access the QDockWidget
|
||||
/// you get it with parentWidget() of the returned widget.
|
||||
QWidget* getDockWindow(const char* name) const;
|
||||
/// Returns the QDockWidget container
|
||||
QDockWidget* getDockContainer(const char* name) const;
|
||||
/// Returns a list of all widgets which set to a QDockWidget.
|
||||
QList<QWidget*> getDockWindows() const;
|
||||
/// If the corresponding dock widget isn't visible then activate it
|
||||
|
||||
324
src/Gui/EditableDatumLabel.cpp
Normal file
324
src/Gui/EditableDatumLabel.cpp
Normal file
@@ -0,0 +1,324 @@
|
||||
/// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2023 Ondsel <development@ondsel.com> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <Inventor/sensors/SoNodeSensor.h>
|
||||
# include <Inventor/nodes/SoAnnotation.h>
|
||||
# include <Inventor/nodes/SoOrthographicCamera.h>
|
||||
# include <Inventor/nodes/SoTransform.h>
|
||||
#endif // _PreComp_
|
||||
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/View3DInventor.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
|
||||
#include "EditableDatumLabel.h"
|
||||
|
||||
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
|
||||
struct NodeData {
|
||||
EditableDatumLabel* label;
|
||||
};
|
||||
|
||||
EditableDatumLabel::EditableDatumLabel(View3DInventorViewer* view,
|
||||
const Base::Placement& plc,
|
||||
SbColor color,
|
||||
bool autoDistance)
|
||||
: isSet(false)
|
||||
, autoDistance(autoDistance)
|
||||
, autoDistanceReverse(false)
|
||||
, viewer(view)
|
||||
, spinBox(nullptr)
|
||||
, cameraSensor(nullptr)
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
root = new SoAnnotation;
|
||||
root->ref();
|
||||
root->renderCaching = SoSeparator::OFF;
|
||||
|
||||
transform = new SoTransform();
|
||||
transform->ref();
|
||||
root->addChild(transform);
|
||||
|
||||
label = new SoDatumLabel();
|
||||
label->ref();
|
||||
label->string = " ";
|
||||
label->textColor = color;
|
||||
label->size.setValue(17);
|
||||
label->lineWidth = 2.0;
|
||||
label->useAntialiasing = false;
|
||||
label->datumtype = SoDatumLabel::DISTANCE;
|
||||
label->param1 = 0.;
|
||||
label->param2 = 0.;
|
||||
if (autoDistance) {
|
||||
setLabelRecommendedDistance();
|
||||
}
|
||||
root->addChild(label);
|
||||
|
||||
setPlacement(plc);
|
||||
// NOLINTEND
|
||||
}
|
||||
|
||||
EditableDatumLabel::~EditableDatumLabel()
|
||||
{
|
||||
deactivate();
|
||||
transform->unref();
|
||||
root->unref();
|
||||
label->unref();
|
||||
}
|
||||
|
||||
void EditableDatumLabel::activate()
|
||||
{
|
||||
if (!viewer) {
|
||||
return;
|
||||
}
|
||||
|
||||
static_cast<SoSeparator*>(viewer->getSceneGraph())->addChild(root); // NOLINT
|
||||
|
||||
//track camera movements to update spinbox position.
|
||||
auto info = new NodeData{ this };
|
||||
cameraSensor = new SoNodeSensor([](void* data, SoSensor* sensor) {
|
||||
Q_UNUSED(sensor);
|
||||
auto info = static_cast<NodeData*>(data);
|
||||
info->label->positionSpinbox();
|
||||
if (info->label->autoDistance) {
|
||||
info->label->setLabelRecommendedDistance();
|
||||
}
|
||||
}, info);
|
||||
cameraSensor->attach(viewer->getCamera());
|
||||
}
|
||||
|
||||
void EditableDatumLabel::deactivate()
|
||||
{
|
||||
stopEdit();
|
||||
|
||||
if (cameraSensor) {
|
||||
auto data = static_cast<NodeData*>(cameraSensor->getData());
|
||||
delete data;
|
||||
cameraSensor->detach();
|
||||
delete cameraSensor;
|
||||
cameraSensor = nullptr;
|
||||
}
|
||||
|
||||
if (viewer) {
|
||||
static_cast<SoSeparator*>(viewer->getSceneGraph())->removeChild(root); // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
void EditableDatumLabel::startEdit(double val, QObject* eventFilteringObj)
|
||||
{
|
||||
QWidget* mdi = viewer->parentWidget();
|
||||
|
||||
label->string = " ";
|
||||
|
||||
spinBox = new QuantitySpinBox(mdi);
|
||||
spinBox->setUnit(Base::Unit::Length);
|
||||
spinBox->setMinimum(-INT_MAX);
|
||||
spinBox->setMaximum(INT_MAX);
|
||||
spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||
spinBox->setKeyboardTracking(false);
|
||||
if (eventFilteringObj) {
|
||||
spinBox->installEventFilter(eventFilteringObj);
|
||||
}
|
||||
|
||||
spinBox->show();
|
||||
setSpinboxValue(val);
|
||||
//Note: adjustSize apparently uses the Min/Max values to set the size. So if we don't set them to INT_MAX, the spinbox are much too big.
|
||||
spinBox->adjustSize();
|
||||
setFocusToSpinbox();
|
||||
|
||||
connect(spinBox, qOverload<double>(&QuantitySpinBox::valueChanged),
|
||||
this, [this](double value) {
|
||||
this->isSet = true;
|
||||
Q_EMIT this->valueChanged(value);
|
||||
});
|
||||
}
|
||||
|
||||
void EditableDatumLabel::stopEdit()
|
||||
{
|
||||
if (spinBox) {
|
||||
spinBox->deleteLater();
|
||||
spinBox = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
double EditableDatumLabel::getValue()
|
||||
{
|
||||
return spinBox->rawValue();
|
||||
}
|
||||
|
||||
void EditableDatumLabel::setSpinboxValue(double val)
|
||||
{
|
||||
if (!spinBox) {
|
||||
Base::Console().Warning("Spinbox doesn't exist in EditableDatumLabel::setSpinboxValue.");
|
||||
return;
|
||||
}
|
||||
|
||||
QSignalBlocker block(spinBox);
|
||||
spinBox->setValue(val);
|
||||
positionSpinbox();
|
||||
|
||||
if (spinBox->hasFocus()) {
|
||||
spinBox->selectNumber();
|
||||
}
|
||||
}
|
||||
|
||||
void EditableDatumLabel::setFocusToSpinbox()
|
||||
{
|
||||
if (!spinBox) {
|
||||
Base::Console().Warning("Spinbox doesn't exist in EditableDatumLabel::setFocusToSpinbox.");
|
||||
return;
|
||||
}
|
||||
|
||||
spinBox->setFocus();
|
||||
spinBox->selectNumber();
|
||||
}
|
||||
|
||||
void EditableDatumLabel::positionSpinbox()
|
||||
{
|
||||
if (!spinBox) {
|
||||
return;
|
||||
}
|
||||
|
||||
QSize wSize = spinBox->size();
|
||||
QPoint pxCoord = viewer->toQPoint(viewer->getPointOnViewport(getTextCenterPoint()));
|
||||
pxCoord.setX(std::max(pxCoord.x() - wSize.width() / 2, 0));
|
||||
pxCoord.setY(std::max(pxCoord.y() - wSize.height() / 2, 0));
|
||||
spinBox->move(pxCoord);
|
||||
}
|
||||
|
||||
SbVec3f EditableDatumLabel::getTextCenterPoint() const
|
||||
{
|
||||
//Here we need the 3d point and not the 2d point as are the SoLabel points.
|
||||
// First we get the 2D point (on the sketch/image plane) of the middle of the text label.
|
||||
SbVec3f point2D = label->textOffset;
|
||||
// Get the translation and rotation values from the transform
|
||||
SbVec3f translation = transform->translation.getValue();
|
||||
SbRotation rotation = transform->rotation.getValue();
|
||||
|
||||
// Calculate the inverse transformation
|
||||
SbVec3f invTranslation = -translation;
|
||||
SbRotation invRotation = rotation.inverse();
|
||||
|
||||
// Transform the 2D coordinates to 3D
|
||||
// Plane form
|
||||
SbVec3f RX(1, 0, 0);
|
||||
SbVec3f RY(0, 1, 0);
|
||||
|
||||
// move to position of Sketch
|
||||
invRotation.multVec(RX, RX);
|
||||
invRotation.multVec(RY, RY);
|
||||
invRotation.multVec(invTranslation, invTranslation);
|
||||
|
||||
// we use invTranslation as the Base because in setPlacement we set transform->translation using
|
||||
// placement.getPosition() to fix the Zoffset. But this applies the X & Y translation too.
|
||||
Base::Vector3d pos(invTranslation[0], invTranslation[1], invTranslation[2]);
|
||||
Base::Vector3d RXb(RX[0], RX[1], RX[2]);
|
||||
Base::Vector3d RYb(RY[0], RY[1], RY[2]);
|
||||
Base::Vector3d P2D(point2D[0], point2D[1], point2D[2]);
|
||||
P2D.TransformToCoordinateSystem(pos, RXb, RYb);
|
||||
|
||||
return {float(P2D.x), float(P2D.y), float(P2D.z)};
|
||||
}
|
||||
|
||||
void EditableDatumLabel::setPlacement(const Base::Placement& plc)
|
||||
{
|
||||
double x{}, y{}, z{}, w{}; // NOLINT
|
||||
plc.getRotation().getValue(x, y, z, w);
|
||||
transform->rotation.setValue(x, y, z, w); // NOLINT
|
||||
|
||||
Base::Vector3d pos = plc.getPosition();
|
||||
transform->translation.setValue(float(pos.x), float(pos.y), float(pos.z));
|
||||
|
||||
Base::Vector3d RN(0, 0, 1);
|
||||
RN = plc.getRotation().multVec(RN);
|
||||
label->norm.setValue(SbVec3f(float(RN.x), float(RN.y), float(RN.z)));
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
void EditableDatumLabel::setColor(SbColor color)
|
||||
{
|
||||
label->textColor = color;
|
||||
}
|
||||
|
||||
void EditableDatumLabel::setFocus()
|
||||
{
|
||||
if (spinBox) {
|
||||
spinBox->selectNumber();
|
||||
}
|
||||
}
|
||||
|
||||
void EditableDatumLabel::setPoints(SbVec3f p1, SbVec3f p2)
|
||||
{
|
||||
label->setPoints(p1, p2);
|
||||
//TODO: here the position of the spinbox is not going to be center of p1, p2 because the point given by getTextCenterPoint
|
||||
// is not updated yet. it will be only on redraw so it is actually positioning on previous position.
|
||||
|
||||
positionSpinbox();
|
||||
if (autoDistance) {
|
||||
setLabelRecommendedDistance();
|
||||
}
|
||||
}
|
||||
|
||||
void EditableDatumLabel::setPoints(Base::Vector3d p1, Base::Vector3d p2)
|
||||
{
|
||||
setPoints(SbVec3f(float(p1.x), float(p1.y), float(p1.z)),
|
||||
SbVec3f(float(p2.x), float(p2.y), float(p2.z)));
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
void EditableDatumLabel::setLabelType(SoDatumLabel::Type type)
|
||||
{
|
||||
label->datumtype = type;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
void EditableDatumLabel::setLabelDistance(double distance)
|
||||
{
|
||||
label->param1 = float(distance);
|
||||
}
|
||||
|
||||
void EditableDatumLabel::setLabelRecommendedDistance()
|
||||
{
|
||||
// Takes the 3d view size, and set the label distance to a % of that, such that the distance does not depend on the zoom level.
|
||||
float width = -1.;
|
||||
float length = -1.;
|
||||
viewer->getDimensions(width, length);
|
||||
|
||||
if (width == -1. || length == -1.) {
|
||||
return;
|
||||
}
|
||||
|
||||
label->param1 = (autoDistanceReverse ? -1.0F : 1.0F) * (width + length) * 0.03F; // NOLINT
|
||||
}
|
||||
|
||||
void EditableDatumLabel::setLabelAutoDistanceReverse(bool val)
|
||||
{
|
||||
autoDistanceReverse = val;
|
||||
}
|
||||
|
||||
#include "moc_EditableDatumLabel.cpp"
|
||||
95
src/Gui/EditableDatumLabel.h
Normal file
95
src/Gui/EditableDatumLabel.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
/****************************************************************************
|
||||
* *
|
||||
* Copyright (c) 2023 Ondsel <development@ondsel.com> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef GUI_EDITABLEDATUMLABEL_H
|
||||
#define GUI_EDITABLEDATUMLABEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <Gui/QuantitySpinBox.h>
|
||||
|
||||
#include "SoDatumLabel.h"
|
||||
|
||||
#include <FCGlobal.h>
|
||||
|
||||
class SoNodeSensor;
|
||||
class SoTransform;
|
||||
|
||||
namespace Gui {
|
||||
|
||||
class View3DInventorViewer;
|
||||
|
||||
|
||||
class GuiExport EditableDatumLabel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(EditableDatumLabel)
|
||||
|
||||
public:
|
||||
EditableDatumLabel(View3DInventorViewer* view, const Base::Placement& plc, SbColor color, bool autoDistance = false);
|
||||
~EditableDatumLabel() override;
|
||||
|
||||
void activate();
|
||||
void deactivate();
|
||||
|
||||
void startEdit(double val, QObject* eventFilteringObj = nullptr);
|
||||
void stopEdit();
|
||||
double getValue();
|
||||
void setSpinboxValue(double val);
|
||||
void setPlacement(const Base::Placement& plc);
|
||||
void setColor(SbColor color);
|
||||
void setFocus();
|
||||
void setPoints(SbVec3f p1, SbVec3f p2);
|
||||
void setPoints(Base::Vector3d p1, Base::Vector3d p2);
|
||||
void setFocusToSpinbox();
|
||||
void setLabelType(SoDatumLabel::Type type);
|
||||
void setLabelDistance(double distance);
|
||||
void setLabelRecommendedDistance();
|
||||
void setLabelAutoDistanceReverse(bool val);
|
||||
|
||||
// NOLINTBEGIN
|
||||
SoDatumLabel* label;
|
||||
bool isSet;
|
||||
bool autoDistance;
|
||||
bool autoDistanceReverse;
|
||||
// NOLINTEND
|
||||
|
||||
Q_SIGNALS:
|
||||
void valueChanged(double val);
|
||||
|
||||
private:
|
||||
void positionSpinbox();
|
||||
SbVec3f getTextCenterPoint() const;
|
||||
|
||||
private:
|
||||
SoSeparator* root;
|
||||
SoTransform* transform;
|
||||
View3DInventorViewer* viewer;
|
||||
QuantitySpinBox* spinBox;
|
||||
SoNodeSensor* cameraSensor;
|
||||
SbVec3f midpos;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // GUI_EDITABLEDATUMLABEL_H
|
||||
@@ -132,8 +132,8 @@ def InitApplications():
|
||||
InstallFile = os.path.join(Dir,"InitGui.py")
|
||||
if os.path.exists(InstallFile):
|
||||
try:
|
||||
with open(file=InstallFile, encoding="utf-8") as f:
|
||||
exec(f.read())
|
||||
with open(InstallFile, 'rt', encoding='utf-8') as f:
|
||||
exec(compile(f.read(), InstallFile, 'exec'))
|
||||
except Exception as inst:
|
||||
Log('Init: Initializing ' + Dir + '... failed\n')
|
||||
Log('-'*100+'\n')
|
||||
|
||||
@@ -469,15 +469,18 @@ void MainWindow::setupDockWindows()
|
||||
if (ht != config.end())
|
||||
hiddenDockWindows = ht->second;
|
||||
|
||||
bool treeView = setupTreeView(hiddenDockWindows);
|
||||
bool propertyView = setupPropertyView(hiddenDockWindows);
|
||||
setupTreeView(hiddenDockWindows);
|
||||
setupPropertyView(hiddenDockWindows);
|
||||
setupTaskView(hiddenDockWindows);
|
||||
setupSelectionView(hiddenDockWindows);
|
||||
setupComboView(hiddenDockWindows, !treeView || !propertyView);
|
||||
setupComboView(hiddenDockWindows);
|
||||
|
||||
// Report view must be created before PythonConsole!
|
||||
setupReportView(hiddenDockWindows);
|
||||
setupPythonConsole(hiddenDockWindows);
|
||||
setupDAGView(hiddenDockWindows);
|
||||
|
||||
this->setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North);
|
||||
}
|
||||
|
||||
bool MainWindow::setupTreeView(const std::string& hiddenDockWindows)
|
||||
@@ -489,7 +492,7 @@ bool MainWindow::setupTreeView(const std::string& hiddenDockWindows)
|
||||
bool enabled = group->GetBool("Enabled", true);
|
||||
if (enabled != group->GetBool("Enabled", false)) {
|
||||
enabled = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
|
||||
->GetGroup("MainWindow")->GetGroup("DockWindows")->GetBool("Std_TreeView",false);
|
||||
->GetGroup("MainWindow")->GetGroup("DockWindows")->GetBool("Std_TreeView", true);
|
||||
}
|
||||
group->SetBool("Enabled", enabled); //ensure entry exists.
|
||||
if (enabled) {
|
||||
@@ -507,6 +510,23 @@ bool MainWindow::setupTreeView(const std::string& hiddenDockWindows)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MainWindow::setupTaskView(const std::string& hiddenDockWindows)
|
||||
{
|
||||
// Task view
|
||||
if (hiddenDockWindows.find("Std_TaskView") == std::string::npos) {
|
||||
auto taskView = new Gui::TaskView::TaskView(this);
|
||||
taskView->setObjectName
|
||||
(QString::fromLatin1(QT_TRANSLATE_NOOP("QDockWidget","Tasks")));
|
||||
taskView->setMinimumWidth(210);
|
||||
|
||||
DockWindowManager* pDockMgr = DockWindowManager::instance();
|
||||
pDockMgr->registerDockWindow("Std_TaskView", taskView);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MainWindow::setupPropertyView(const std::string& hiddenDockWindows)
|
||||
{
|
||||
// Property view
|
||||
@@ -517,7 +537,7 @@ bool MainWindow::setupPropertyView(const std::string& hiddenDockWindows)
|
||||
bool enabled = group->GetBool("Enabled", true);
|
||||
if (enabled != group->GetBool("Enabled", false)) {
|
||||
enabled = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
|
||||
->GetGroup("MainWindow")->GetGroup("DockWindows")->GetBool("Std_PropertyView",false);
|
||||
->GetGroup("MainWindow")->GetGroup("DockWindows")->GetBool("Std_PropertyView", true);
|
||||
}
|
||||
group->SetBool("Enabled", enabled); //ensure entry exists.
|
||||
if (enabled) {
|
||||
@@ -552,23 +572,23 @@ bool MainWindow::setupSelectionView(const std::string& hiddenDockWindows)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MainWindow::setupComboView(const std::string& hiddenDockWindows, bool enable)
|
||||
bool MainWindow::setupComboView(const std::string& hiddenDockWindows)
|
||||
{
|
||||
// Combo view
|
||||
if (hiddenDockWindows.find("Std_ComboView") == std::string::npos) {
|
||||
if (!enable) {
|
||||
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
|
||||
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("DockWindows")->GetGroup("ComboView");
|
||||
enable = group->GetBool("Enabled", true);
|
||||
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
|
||||
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("DockWindows")->GetGroup("ComboView");
|
||||
bool enable = group->GetBool("Enabled", false);
|
||||
|
||||
if (enable) {
|
||||
auto pcComboView = new ComboView(nullptr, this);
|
||||
pcComboView->setObjectName(QString::fromLatin1(QT_TRANSLATE_NOOP("QDockWidget", "Model")));
|
||||
pcComboView->setMinimumWidth(150);
|
||||
|
||||
DockWindowManager* pDockMgr = DockWindowManager::instance();
|
||||
pDockMgr->registerDockWindow("Std_ComboView", pcComboView);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto pcComboView = new ComboView(enable, nullptr, this);
|
||||
pcComboView->setObjectName(QString::fromLatin1(QT_TRANSLATE_NOOP("QDockWidget","Combo View")));
|
||||
pcComboView->setMinimumWidth(150);
|
||||
|
||||
DockWindowManager* pDockMgr = DockWindowManager::instance();
|
||||
pDockMgr->registerDockWindow("Std_ComboView", pcComboView);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -284,9 +284,10 @@ protected:
|
||||
private:
|
||||
void setupDockWindows();
|
||||
bool setupTreeView(const std::string&);
|
||||
bool setupTaskView(const std::string&);
|
||||
bool setupPropertyView(const std::string&);
|
||||
bool setupSelectionView(const std::string&);
|
||||
bool setupComboView(const std::string&, bool enable);
|
||||
bool setupComboView(const std::string&);
|
||||
bool setupDAGView(const std::string&);
|
||||
bool setupReportView(const std::string&);
|
||||
bool setupPythonConsole(const std::string&);
|
||||
|
||||
@@ -243,23 +243,7 @@ void DlgSettingsGeneral::saveSettings()
|
||||
int blinkTime{hGrp->GetBool("EnableCursorBlinking", true) ? -1 : 0};
|
||||
qApp->setCursorFlashTime(blinkTime);
|
||||
|
||||
hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DockWindows");
|
||||
bool treeView=false;
|
||||
bool propertyView=false;
|
||||
bool comboView=true;
|
||||
switch(ui->treeMode->currentIndex()) {
|
||||
case 1:
|
||||
treeView = propertyView = true;
|
||||
comboView = false;
|
||||
break;
|
||||
case 2:
|
||||
comboView = true;
|
||||
treeView = propertyView = true;
|
||||
break;
|
||||
}
|
||||
hGrp->GetGroup("ComboView")->SetBool("Enabled",comboView);
|
||||
hGrp->GetGroup("TreeView")->SetBool("Enabled",treeView);
|
||||
hGrp->GetGroup("PropertyView")->SetBool("Enabled",propertyView);
|
||||
saveDockWindowVisibility();
|
||||
|
||||
hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow");
|
||||
hGrp->SetBool("TiledBackground", ui->tiledBackground->isChecked());
|
||||
@@ -365,20 +349,7 @@ void DlgSettingsGeneral::loadSettings()
|
||||
ui->toolbarIconSize->setCurrentIndex(index);
|
||||
|
||||
//TreeMode combobox setup.
|
||||
ui->treeMode->clear();
|
||||
ui->treeMode->addItem(tr("Combo View"));
|
||||
ui->treeMode->addItem(tr("TreeView and PropertyView"));
|
||||
ui->treeMode->addItem(tr("Both"));
|
||||
|
||||
hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DockWindows");
|
||||
bool propertyView = hGrp->GetGroup("PropertyView")->GetBool("Enabled",false);
|
||||
bool treeView = hGrp->GetGroup("TreeView")->GetBool("Enabled",false);
|
||||
bool comboView = hGrp->GetGroup("ComboView")->GetBool("Enabled",true);
|
||||
index = 0;
|
||||
if(propertyView || treeView) {
|
||||
index = comboView?2:1;
|
||||
}
|
||||
ui->treeMode->setCurrentIndex(index);
|
||||
loadDockWindowVisibility();
|
||||
|
||||
hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow");
|
||||
ui->tiledBackground->setChecked(hGrp->GetBool("TiledBackground", false));
|
||||
@@ -464,6 +435,48 @@ void DlgSettingsGeneral::changeEvent(QEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void DlgSettingsGeneral::saveDockWindowVisibility()
|
||||
{
|
||||
auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DockWindows");
|
||||
bool treeView = hGrp->GetGroup("TreeView")->GetBool("Enabled", true);
|
||||
bool propertyView = hGrp->GetGroup("PropertyView")->GetBool("Enabled", true);
|
||||
bool comboView = hGrp->GetGroup("ComboView")->GetBool("Enabled", false);
|
||||
switch (ui->treeMode->currentIndex()) {
|
||||
case 0:
|
||||
comboView = true;
|
||||
treeView = propertyView = false;
|
||||
break;
|
||||
case 1:
|
||||
treeView = propertyView = true;
|
||||
comboView = false;
|
||||
break;
|
||||
}
|
||||
|
||||
hGrp->GetGroup("ComboView")->SetBool("Enabled", comboView);
|
||||
hGrp->GetGroup("TreeView")->SetBool("Enabled", treeView);
|
||||
hGrp->GetGroup("PropertyView")->SetBool("Enabled", propertyView);
|
||||
}
|
||||
|
||||
void DlgSettingsGeneral::loadDockWindowVisibility()
|
||||
{
|
||||
ui->treeMode->clear();
|
||||
ui->treeMode->addItem(tr("Combo View"));
|
||||
ui->treeMode->addItem(tr("TreeView and PropertyView"));
|
||||
|
||||
auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DockWindows");
|
||||
bool propertyView = hGrp->GetGroup("PropertyView")->GetBool("Enabled", true);
|
||||
bool treeView = hGrp->GetGroup("TreeView")->GetBool("Enabled", true);
|
||||
bool comboView = hGrp->GetGroup("ComboView")->GetBool("Enabled", false);
|
||||
int index = -1;
|
||||
if (propertyView || treeView) {
|
||||
index = 1;
|
||||
}
|
||||
else if (comboView) {
|
||||
index = 0;
|
||||
}
|
||||
ui->treeMode->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void DlgSettingsGeneral::recreatePreferencePackMenu()
|
||||
{
|
||||
ui->PreferencePacks->setRowCount(0); // Begin by clearing whatever is there
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#ifndef GUI_DIALOG_DLGSETTINGSGENERAL_H
|
||||
#define GUI_DIALOG_DLGSETTINGSGENERAL_H
|
||||
|
||||
|
||||
#include <Gui/PropertyPage.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -73,6 +73,8 @@ public Q_SLOTS:
|
||||
void on_checkBox_projectUnitSystemIgnore_stateChanged(int state);
|
||||
|
||||
private:
|
||||
void saveDockWindowVisibility();
|
||||
void loadDockWindowVisibility();
|
||||
void setRecentFileSize();
|
||||
void saveAsNewPreferencePack();
|
||||
void revertToSavedConfig();
|
||||
@@ -92,4 +94,4 @@ private:
|
||||
} // namespace Dialog
|
||||
} // namespace Gui
|
||||
|
||||
#endif // GUI_DIALOG_DLGSETTINGSGENERAL_H
|
||||
#endif // GUI_DIALOG_DLGSETTINGSGENERAL_H
|
||||
|
||||
@@ -97,6 +97,7 @@ SoDatumLabel::SoDatumLabel()
|
||||
this->imgWidth = 0;
|
||||
this->imgHeight = 0;
|
||||
this->glimagevalid = false;
|
||||
this->textOffset = SbVec3f(0.f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
void SoDatumLabel::drawImage()
|
||||
@@ -433,19 +434,11 @@ private:
|
||||
|
||||
void SoDatumLabel::computeBBox(SoAction * action, SbBox3f &box, SbVec3f ¢er)
|
||||
{
|
||||
if (!this->bbox.isEmpty()) {
|
||||
// Set the bounding box using stored parameters
|
||||
box.setBounds(this->bbox.getMin(),this->bbox.getMax() );
|
||||
SbVec3f bbcenter = this->bbox.getCenter();
|
||||
center.setValue(bbcenter[0], bbcenter[1], bbcenter[2]);
|
||||
}
|
||||
else {
|
||||
SoState *state = action->getState();
|
||||
float scale = getScaleFactor(state);
|
||||
SoState *state = action->getState();
|
||||
float scale = getScaleFactor(state);
|
||||
|
||||
DatumLabelBox datumBox(scale, this);
|
||||
datumBox.computeBBox(box, center);
|
||||
}
|
||||
DatumLabelBox datumBox(scale, this);
|
||||
datumBox.computeBBox(box, center);
|
||||
}
|
||||
|
||||
void SoDatumLabel::generateDistancePrimitives(SoAction * action, const SbVec3f& p1, const SbVec3f& p2)
|
||||
@@ -485,7 +478,7 @@ void SoDatumLabel::generateDistancePrimitives(SoAction * action, const SbVec3f&
|
||||
img3 = SbVec3f((img3[0] * c) - (img3[1] * s), (img3[0] * s) + (img3[1] * c), 0.f);
|
||||
img4 = SbVec3f((img4[0] * c) - (img4[1] * s), (img4[0] * s) + (img4[1] * c), 0.f);
|
||||
|
||||
SbVec3f textOffset = midpos + normal * length + dir * length2;
|
||||
textOffset = midpos + normal * length + dir * length2;
|
||||
|
||||
img1 += textOffset;
|
||||
img2 += textOffset;
|
||||
@@ -539,7 +532,7 @@ void SoDatumLabel::generateDiameterPrimitives(SoAction * action, const SbVec3f&
|
||||
img3 = SbVec3f((img3[0] * c) - (img3[1] * s), (img3[0] * s) + (img3[1] * c), 0.f);
|
||||
img4 = SbVec3f((img4[0] * c) - (img4[1] * s), (img4[0] * s) + (img4[1] * c), 0.f);
|
||||
|
||||
SbVec3f textOffset = pos;
|
||||
textOffset = pos;
|
||||
|
||||
img1 += textOffset;
|
||||
img2 += textOffset;
|
||||
@@ -585,7 +578,7 @@ void SoDatumLabel::generateAnglePrimitives(SoAction * action, const SbVec3f& p0)
|
||||
// p0 - vector for angle intersect
|
||||
SbVec3f v0(cos(startangle+range/2),sin(startangle+range/2),0);
|
||||
|
||||
SbVec3f textOffset = p0 + v0 * r;
|
||||
textOffset = p0 + v0 * r;
|
||||
|
||||
SbVec3f img1 = SbVec3f(-this->imgWidth / 2, -this->imgHeight / 2, 0.f);
|
||||
SbVec3f img2 = SbVec3f(-this->imgWidth / 2, this->imgHeight / 2, 0.f);
|
||||
@@ -821,8 +814,6 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
// Position for Datum Text Label
|
||||
float angle = 0;
|
||||
|
||||
SbVec3f textOffset;
|
||||
|
||||
// Get the colour
|
||||
const SbColor& t = textColor.getValue();
|
||||
|
||||
@@ -913,13 +904,13 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
}
|
||||
// Perp Lines
|
||||
glBegin(GL_LINES);
|
||||
if (length != 0.) {
|
||||
glVertex2f(p1[0], p1[1]);
|
||||
glVertex2f(perp1[0], perp1[1]);
|
||||
if (length != 0.) {
|
||||
glVertex2f(p1[0], p1[1]);
|
||||
glVertex2f(perp1[0], perp1[1]);
|
||||
|
||||
glVertex2f(p2[0], p2[1]);
|
||||
glVertex2f(perp2[0], perp2[1]);
|
||||
}
|
||||
glVertex2f(p2[0], p2[1]);
|
||||
glVertex2f(perp2[0], perp2[1]);
|
||||
}
|
||||
|
||||
glVertex2f(par1[0], par1[1]);
|
||||
glVertex2f(par2[0], par2[1]);
|
||||
@@ -946,30 +937,6 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
glVertex2f(ar3[0], ar3[1]);
|
||||
glVertex2f(ar4[0], ar4[1]);
|
||||
glEnd();
|
||||
|
||||
// BOUNDING BOX CALCULATION - IMPORTANT
|
||||
// Finds the mins and maxes
|
||||
std::vector<SbVec3f> corners;
|
||||
corners.push_back(p1);
|
||||
corners.push_back(p2);
|
||||
corners.push_back(perp1);
|
||||
corners.push_back(perp2);
|
||||
|
||||
// Make sure that the label is inside the bounding box
|
||||
corners.push_back(textOffset + dir * (this->imgWidth / 2 + margin) + normal * (srch + margin));
|
||||
corners.push_back(textOffset - dir * (this->imgWidth / 2 + margin) + normal * (srch + margin));
|
||||
corners.push_back(textOffset + dir * (this->imgWidth / 2 + margin) - normal * margin);
|
||||
corners.push_back(textOffset - dir * (this->imgWidth / 2 + margin) - normal * margin);
|
||||
|
||||
float minX = p1[0], minY = p1[1], maxX = p1[0] , maxY = p1[1];
|
||||
for (SbVec3f it : corners) {
|
||||
minX = (it[0] < minX) ? it[0] : minX;
|
||||
minY = (it[1] < minY) ? it[1] : minY;
|
||||
maxX = (it[0] > maxX) ? it[0] : maxX;
|
||||
maxY = (it[1] > maxY) ? it[1] : maxY;
|
||||
}
|
||||
//Store the bounding box
|
||||
this->bbox.setBounds(SbVec3f(minX, minY, 0.f), SbVec3f (maxX, maxY, 0.f));
|
||||
}
|
||||
else if (this->datumtype.getValue() == RADIUS || this->datumtype.getValue() == DIAMETER) {
|
||||
// Get the Points
|
||||
@@ -1039,23 +1006,6 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
|
||||
}
|
||||
|
||||
// BOUNDING BOX CALCULATION - IMPORTANT
|
||||
// Finds the mins and maxes
|
||||
std::vector<SbVec3f> corners;
|
||||
corners.push_back(p1);
|
||||
corners.push_back(p2);
|
||||
corners.push_back(pnt1);
|
||||
corners.push_back(pnt2);
|
||||
|
||||
float minX = p1[0], minY = p1[1], maxX = p1[0] , maxY = p1[1];
|
||||
for (SbVec3f it : corners) {
|
||||
minX = (it[0] < minX) ? it[0] : minX;
|
||||
minY = (it[1] < minY) ? it[1] : minY;
|
||||
maxX = (it[0] > maxX) ? it[0] : maxX;
|
||||
maxY = (it[1] > maxY) ? it[1] : maxY;
|
||||
}
|
||||
//Store the bounding box
|
||||
this->bbox.setBounds(SbVec3f(minX, minY, 0.f), SbVec3f (maxX, maxY, 0.f));
|
||||
} else if (this->datumtype.getValue() == ANGLE) {
|
||||
// Only the angle intersection point is needed
|
||||
SbVec3f p0 = points[0];
|
||||
@@ -1125,39 +1075,6 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
glVertex2f(pnt4[0],pnt4[1]);
|
||||
glEnd();
|
||||
|
||||
// BOUNDING BOX CALCULATION - IMPORTANT
|
||||
// Finds the mins and maxes
|
||||
// We may need to include the text position too
|
||||
|
||||
SbVec3f img1 = SbVec3f(-this->imgWidth / 2, -this->imgHeight / 2, 0.f);
|
||||
SbVec3f img2 = SbVec3f(-this->imgWidth / 2, this->imgHeight / 2, 0.f);
|
||||
SbVec3f img3 = SbVec3f( this->imgWidth / 2, -this->imgHeight / 2, 0.f);
|
||||
SbVec3f img4 = SbVec3f( this->imgWidth / 2, this->imgHeight / 2, 0.f);
|
||||
|
||||
img1 += textOffset;
|
||||
img2 += textOffset;
|
||||
img3 += textOffset;
|
||||
img4 += textOffset;
|
||||
|
||||
std::vector<SbVec3f> corners;
|
||||
corners.push_back(pnt1);
|
||||
corners.push_back(pnt2);
|
||||
corners.push_back(pnt3);
|
||||
corners.push_back(pnt4);
|
||||
corners.push_back(img1);
|
||||
corners.push_back(img2);
|
||||
corners.push_back(img3);
|
||||
corners.push_back(img4);
|
||||
|
||||
float minX = pnt1[0], minY = pnt1[1], maxX = pnt1[0] , maxY = pnt1[1];
|
||||
for (SbVec3f it : corners) {
|
||||
minX = (it[0] < minX) ? it[0] : minX;
|
||||
minY = (it[1] < minY) ? it[1] : minY;
|
||||
maxX = (it[0] > maxX) ? it[0] : maxX;
|
||||
maxY = (it[1] > maxY) ? it[1] : maxY;
|
||||
}
|
||||
//Store the bounding box
|
||||
this->bbox.setBounds(SbVec3f(minX, minY, 0.f), SbVec3f (maxX, maxY, 0.f));
|
||||
} else if (this->datumtype.getValue() == SYMMETRIC) {
|
||||
|
||||
SbVec3f p1 = points[0];
|
||||
@@ -1200,22 +1117,6 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
glVertex3f(ar3[0], ar3[1], ZCONSTR);
|
||||
glVertex3f(ar5[0], ar5[1], ZCONSTR);
|
||||
glEnd();
|
||||
|
||||
// BOUNDING BOX CALCULATION - IMPORTANT
|
||||
// Finds the mins and maxes
|
||||
std::vector<SbVec3f> corners;
|
||||
corners.push_back(p1);
|
||||
corners.push_back(p2);
|
||||
|
||||
float minX = p1[0], minY = p1[1], maxX = p1[0] , maxY = p1[1];
|
||||
for (SbVec3f it : corners) {
|
||||
minX = (it[0] < minX) ? it[0] : minX;
|
||||
minY = (it[1] < minY) ? it[1] : minY;
|
||||
maxX = (it[0] > maxX) ? it[0] : maxX;
|
||||
maxY = (it[1] > maxY) ? it[1] : maxY;
|
||||
}
|
||||
//Store the bounding box
|
||||
this->bbox.setBounds(SbVec3f(minX, minY, 0.f), SbVec3f (maxX, maxY, 0.f));
|
||||
}
|
||||
|
||||
if (hasText) {
|
||||
|
||||
@@ -77,6 +77,7 @@ public:
|
||||
SoSFImage image;
|
||||
SoSFFloat lineWidth;
|
||||
bool useAntialiasing;
|
||||
SbVec3f textOffset;
|
||||
|
||||
protected:
|
||||
~SoDatumLabel() override = default;
|
||||
@@ -94,7 +95,6 @@ private:
|
||||
|
||||
private:
|
||||
void drawImage();
|
||||
SbBox3f bbox;
|
||||
float imgWidth;
|
||||
float imgHeight;
|
||||
bool glimagevalid;
|
||||
|
||||
@@ -27,11 +27,15 @@
|
||||
#include <Inventor/SbRotation.h>
|
||||
#include <Inventor/actions/SoGLRenderAction.h>
|
||||
#include <Inventor/engines/SoComposeVec3f.h>
|
||||
#include <Inventor/elements/SoLazyElement.h>
|
||||
#include <Inventor/nodes/SoLightModel.h>
|
||||
#include <Inventor/nodes/SoDrawStyle.h>
|
||||
#include <Inventor/nodes/SoAnnotation.h>
|
||||
#include <Inventor/nodes/SoBaseColor.h>
|
||||
#include <Inventor/nodes/SoCone.h>
|
||||
#include <Inventor/nodes/SoCoordinate3.h>
|
||||
#include <Inventor/nodes/SoCylinder.h>
|
||||
#include <Inventor/nodes/SoCube.h>
|
||||
#include <Inventor/nodes/SoGroup.h>
|
||||
#include <Inventor/nodes/SoLineSet.h>
|
||||
#include <Inventor/nodes/SoOrthographicCamera.h>
|
||||
@@ -45,6 +49,8 @@
|
||||
#endif
|
||||
|
||||
#include <Base/Quantity.h>
|
||||
#include "Gui/ViewParams.h"
|
||||
#include "App/Color.h"
|
||||
|
||||
#include "SoFCCSysDragger.h"
|
||||
#include "MainWindow.h"
|
||||
@@ -164,10 +170,14 @@ SoGroup* TDragger::buildGeometry()
|
||||
|
||||
//cylinder
|
||||
float cylinderHeight = 10.0;
|
||||
float cylinderRadius = 0.2f;
|
||||
float cylinderRadius = 0.1f;
|
||||
auto cylinderSeparator = new SoSeparator();
|
||||
root->addChild(cylinderSeparator);
|
||||
|
||||
auto cylinderLightModel = new SoLightModel();
|
||||
cylinderLightModel->model = SoLightModel::BASE_COLOR;
|
||||
cylinderSeparator->addChild(cylinderLightModel);
|
||||
|
||||
auto cylinderTranslation = new SoTranslation();
|
||||
cylinderTranslation->translation.setValue(0.0, cylinderHeight / 2.0, 0.0);
|
||||
cylinderSeparator->addChild(cylinderTranslation);
|
||||
@@ -178,11 +188,15 @@ SoGroup* TDragger::buildGeometry()
|
||||
cylinderSeparator->addChild(cylinder);
|
||||
|
||||
//cone
|
||||
float coneBottomRadius = 1.0;
|
||||
float coneHeight = 2.0;
|
||||
float coneBottomRadius = 0.8;
|
||||
float coneHeight = 2.5;
|
||||
auto coneSeparator = new SoSeparator();
|
||||
root->addChild(coneSeparator);
|
||||
|
||||
auto coneLightModel = new SoLightModel();
|
||||
coneLightModel->model = SoLightModel::BASE_COLOR;
|
||||
coneSeparator->addChild(coneLightModel);
|
||||
|
||||
auto pickStyle = new SoPickStyle();
|
||||
pickStyle->style.setValue(SoPickStyle::SHAPE);
|
||||
pickStyle->setOverride(TRUE);
|
||||
@@ -357,13 +371,292 @@ SbVec3f TDragger::roundTranslation(const SbVec3f &vecIn, float incrementIn)
|
||||
translationIncrementCount.setValue(yCount);
|
||||
|
||||
SbVec3f out;
|
||||
out[0] = 0.0;
|
||||
out[0] = 0;
|
||||
out[1] = static_cast<float>(yCount) * incrementIn;
|
||||
out[2] = 0.0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
SO_KIT_SOURCE(TPlanarDragger)
|
||||
|
||||
void TPlanarDragger::initClass()
|
||||
{
|
||||
SO_KIT_INIT_CLASS(TPlanarDragger, SoDragger, "Dragger");
|
||||
}
|
||||
|
||||
TPlanarDragger::TPlanarDragger()
|
||||
{
|
||||
SO_KIT_CONSTRUCTOR(TPlanarDragger);
|
||||
|
||||
SO_KIT_ADD_CATALOG_ENTRY(planarTranslatorSwitch, SoSwitch, TRUE, geomSeparator, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(planarTranslator, SoSeparator, TRUE, planarTranslatorSwitch, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(planarTranslatorActive, SoSeparator, TRUE, planarTranslatorSwitch, "", TRUE);
|
||||
|
||||
if (SO_KIT_IS_FIRST_INSTANCE())
|
||||
buildFirstInstance();
|
||||
|
||||
SO_KIT_ADD_FIELD(translation, (0.0, 0.0, 0.0));
|
||||
SO_KIT_ADD_FIELD(translationIncrement, (1.0));
|
||||
SO_KIT_ADD_FIELD(translationIncrementXCount, (0));
|
||||
SO_KIT_ADD_FIELD(translationIncrementYCount, (0));
|
||||
SO_KIT_ADD_FIELD(autoScaleResult, (1.0));
|
||||
|
||||
SO_KIT_INIT_INSTANCE();
|
||||
|
||||
// initialize default parts.
|
||||
// first is from 'SO_KIT_CATALOG_ENTRY_HEADER' macro
|
||||
// second is unique name from buildFirstInstance().
|
||||
this->setPartAsDefault("planarTranslator", "CSysDynamics_TPlanarDragger_Translator");
|
||||
this->setPartAsDefault("planarTranslatorActive", "CSysDynamics_TPlanarDragger_TranslatorActive");
|
||||
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "planarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, 0);
|
||||
|
||||
this->addStartCallback(&TPlanarDragger::startCB);
|
||||
this->addMotionCallback(&TPlanarDragger::motionCB);
|
||||
this->addFinishCallback(&TPlanarDragger::finishCB);
|
||||
|
||||
addValueChangedCallback(&TPlanarDragger::valueChangedCB);
|
||||
|
||||
fieldSensor.setFunction(&TPlanarDragger::fieldSensorCB);
|
||||
fieldSensor.setData(this);
|
||||
fieldSensor.setPriority(0);
|
||||
|
||||
this->setUpConnections(TRUE, TRUE);
|
||||
}
|
||||
|
||||
TPlanarDragger::~TPlanarDragger()
|
||||
{
|
||||
fieldSensor.setData(nullptr);
|
||||
fieldSensor.detach();
|
||||
|
||||
this->removeStartCallback(&TPlanarDragger::startCB);
|
||||
this->removeMotionCallback(&TPlanarDragger::motionCB);
|
||||
this->removeFinishCallback(&TPlanarDragger::finishCB);
|
||||
removeValueChangedCallback(&TPlanarDragger::valueChangedCB);
|
||||
}
|
||||
|
||||
void TPlanarDragger::buildFirstInstance()
|
||||
{
|
||||
SoGroup *geometryGroup = buildGeometry();
|
||||
|
||||
auto localTranslator = new SoSeparator();
|
||||
localTranslator->setName("CSysDynamics_TPlanarDragger_Translator");
|
||||
localTranslator->addChild(geometryGroup);
|
||||
SoFCDB::getStorage()->addChild(localTranslator);
|
||||
|
||||
auto localTranslatorActive = new SoSeparator();
|
||||
localTranslatorActive->setName("CSysDynamics_TPlanarDragger_TranslatorActive");
|
||||
auto colorActive = new SoBaseColor();
|
||||
colorActive->rgb.setValue(1.0, 1.0, 0.0);
|
||||
localTranslatorActive->addChild(colorActive);
|
||||
localTranslatorActive->addChild(geometryGroup);
|
||||
SoFCDB::getStorage()->addChild(localTranslatorActive);
|
||||
}
|
||||
|
||||
SoGroup* TPlanarDragger::buildGeometry()
|
||||
{
|
||||
auto root = new SoGroup();
|
||||
|
||||
float cubeWidthHeight = 2.0;
|
||||
float cubeDepth = 0.1f;
|
||||
|
||||
auto translation = new SoTranslation();
|
||||
translation->translation.setValue(cubeWidthHeight + 0.15, cubeWidthHeight + 0.15, 0.0);
|
||||
root->addChild(translation);
|
||||
|
||||
auto pickStyle = new SoPickStyle();
|
||||
pickStyle->style.setValue(SoPickStyle::SHAPE);
|
||||
pickStyle->setOverride(TRUE);
|
||||
root->addChild(pickStyle);
|
||||
|
||||
auto lightModel = new SoLightModel();
|
||||
lightModel->model = SoLightModel::BASE_COLOR;
|
||||
root->addChild(lightModel);
|
||||
|
||||
auto cube = new SoCube();
|
||||
cube->width.setValue(cubeWidthHeight);
|
||||
cube->height.setValue(cubeWidthHeight);
|
||||
cube->depth.setValue(cubeDepth);
|
||||
root->addChild(cube);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
void TPlanarDragger::startCB(void *, SoDragger *d)
|
||||
{
|
||||
auto sudoThis = static_cast<TPlanarDragger *>(d);
|
||||
assert(sudoThis);
|
||||
sudoThis->dragStart();
|
||||
}
|
||||
|
||||
void TPlanarDragger::motionCB(void *, SoDragger *d)
|
||||
{
|
||||
auto sudoThis = static_cast<TPlanarDragger *>(d);
|
||||
assert(sudoThis);
|
||||
sudoThis->drag();
|
||||
}
|
||||
|
||||
void TPlanarDragger::finishCB(void *, SoDragger *d)
|
||||
{
|
||||
auto sudoThis = static_cast<TPlanarDragger *>(d);
|
||||
assert(sudoThis);
|
||||
sudoThis->dragFinish();
|
||||
}
|
||||
|
||||
void TPlanarDragger::fieldSensorCB(void *f, SoSensor *)
|
||||
{
|
||||
auto sudoThis = static_cast<TPlanarDragger *>(f);
|
||||
|
||||
if(!f)
|
||||
return;
|
||||
|
||||
SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft
|
||||
sudoThis->workFieldsIntoTransform(matrix);
|
||||
sudoThis->setMotionMatrix(matrix);
|
||||
}
|
||||
|
||||
void TPlanarDragger::valueChangedCB(void *, SoDragger *d)
|
||||
{
|
||||
auto sudoThis = dynamic_cast<TPlanarDragger *>(d);
|
||||
assert(sudoThis);
|
||||
SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft
|
||||
|
||||
//all this just to get the translation?
|
||||
SbVec3f trans, scaleDummy;
|
||||
SbRotation rotationDummy, scaleOrientationDummy;
|
||||
matrix.getTransform(trans, rotationDummy, scaleDummy, scaleOrientationDummy);
|
||||
|
||||
sudoThis->fieldSensor.detach();
|
||||
if (sudoThis->translation.getValue() != trans)
|
||||
sudoThis->translation = trans;
|
||||
sudoThis->fieldSensor.attach(&sudoThis->translation);
|
||||
}
|
||||
|
||||
void TPlanarDragger::dragStart()
|
||||
{
|
||||
SoSwitch *sw;
|
||||
sw = SO_GET_ANY_PART(this, "planarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, 1);
|
||||
|
||||
projector.setViewVolume(this->getViewVolume());
|
||||
projector.setWorkingSpace(this->getLocalToWorldMatrix());
|
||||
projector.setPlane(SbPlane(SbVec3f(0.0, 0.0, 0.0), SbVec3f(1.0, 0.0, 0.0), SbVec3f(0.0, 1.0, 0.0)));
|
||||
SbVec3f hitPoint = projector.project(getNormalizedLocaterPosition());
|
||||
|
||||
SbMatrix localToWorld = getLocalToWorldMatrix();
|
||||
localToWorld.multVecMatrix(hitPoint, hitPoint);
|
||||
setStartingPoint((hitPoint));
|
||||
|
||||
translationIncrementXCount.setValue(0);
|
||||
translationIncrementYCount.setValue(0);
|
||||
}
|
||||
void TPlanarDragger::drag()
|
||||
{
|
||||
projector.setViewVolume(this->getViewVolume());
|
||||
projector.setWorkingSpace(this->getLocalToWorldMatrix());
|
||||
|
||||
SbVec3f hitPoint = projector.project(getNormalizedLocaterPosition());
|
||||
SbVec3f startingPoint = getLocalStartingPoint();
|
||||
SbVec3f localMovement = hitPoint - startingPoint;
|
||||
|
||||
//scale the increment to match local space.
|
||||
float scaledIncrement = static_cast<float>(translationIncrement.getValue()) / autoScaleResult.getValue();
|
||||
|
||||
localMovement = roundTranslation(localMovement, scaledIncrement);
|
||||
//when the movement vector is null either the appendTranslation or
|
||||
//the setMotionMatrix doesn't work. either way it stops translating
|
||||
//back to its initial starting point.
|
||||
if (localMovement.equals(SbVec3f(0.0, 0.0, 0.0), 0.00001f))
|
||||
{
|
||||
setMotionMatrix(getStartMotionMatrix());
|
||||
//don't know why I need the following but if I don't have it
|
||||
//it won't return to original position.
|
||||
this->valueChanged();
|
||||
}
|
||||
else
|
||||
setMotionMatrix(appendTranslation(getStartMotionMatrix(), localMovement));
|
||||
|
||||
Base::Quantity quantityX(
|
||||
static_cast<double>(translationIncrementXCount.getValue()) * translationIncrement.getValue(), Base::Unit::Length);
|
||||
Base::Quantity quantityY(
|
||||
static_cast<double>(translationIncrementYCount.getValue()) * translationIncrement.getValue(), Base::Unit::Length);
|
||||
|
||||
QString message = QString::fromLatin1("%1 %2, %3")
|
||||
.arg(QObject::tr("Translation XY:"), quantityX.getUserString(), quantityY.getUserString());
|
||||
getMainWindow()->showMessage(message, 3000);
|
||||
}
|
||||
|
||||
void TPlanarDragger::dragFinish()
|
||||
{
|
||||
SoSwitch *sw;
|
||||
sw = SO_GET_ANY_PART(this, "planarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, 0);
|
||||
}
|
||||
|
||||
SbBool TPlanarDragger::setUpConnections(SbBool onoff, SbBool doitalways)
|
||||
{
|
||||
if (!doitalways && this->connectionsSetUp == onoff)
|
||||
return onoff;
|
||||
|
||||
SbBool oldval = this->connectionsSetUp;
|
||||
|
||||
if (onoff)
|
||||
{
|
||||
inherited::setUpConnections(onoff, doitalways);
|
||||
TPlanarDragger::fieldSensorCB(this, nullptr);
|
||||
if (this->fieldSensor.getAttachedField() != &this->translation)
|
||||
this->fieldSensor.attach(&this->translation);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->fieldSensor.getAttachedField())
|
||||
this->fieldSensor.detach();
|
||||
inherited::setUpConnections(onoff, doitalways);
|
||||
}
|
||||
this->connectionsSetUp = onoff;
|
||||
return oldval;
|
||||
}
|
||||
|
||||
SbVec3f TPlanarDragger::roundTranslation(const SbVec3f &vecIn, float incrementIn)
|
||||
{
|
||||
int xCount = 0;
|
||||
float xValue = vecIn[0];
|
||||
|
||||
if (fabs(xValue) > (incrementIn / 2.0))
|
||||
{
|
||||
xCount = static_cast<int>(xValue / incrementIn);
|
||||
float remainder = fmod(xValue, incrementIn);
|
||||
if (remainder >= (incrementIn / 2.0))
|
||||
xCount++;
|
||||
}
|
||||
|
||||
translationIncrementXCount.setValue(xCount);
|
||||
|
||||
int yCount = 0;
|
||||
float yValue = vecIn[1];
|
||||
|
||||
if (fabs(yValue) > (incrementIn / 2.0))
|
||||
{
|
||||
yCount = static_cast<int>(yValue / incrementIn);
|
||||
float remainder = fmod(yValue, incrementIn);
|
||||
if (remainder >= (incrementIn / 2.0))
|
||||
yCount++;
|
||||
}
|
||||
|
||||
translationIncrementYCount.setValue(yCount);
|
||||
|
||||
SbVec3f out;
|
||||
out[0] = static_cast<float>(xCount) * incrementIn;
|
||||
out[1] = static_cast<float>(yCount) * incrementIn;
|
||||
out[2] = 0.0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
SO_KIT_SOURCE(RDragger)
|
||||
|
||||
void RDragger::initClass()
|
||||
@@ -448,7 +741,7 @@ SoGroup* RDragger::buildGeometry()
|
||||
//arc
|
||||
auto coordinates = new SoCoordinate3();
|
||||
|
||||
unsigned int segments = 6;
|
||||
unsigned int segments = 15;
|
||||
|
||||
float angleIncrement = static_cast<float>(M_PI / 2.0) / static_cast<float>(segments);
|
||||
SbRotation rotation(SbVec3f(0.0, 0.0, 1.0), angleIncrement);
|
||||
@@ -460,6 +753,14 @@ SoGroup* RDragger::buildGeometry()
|
||||
}
|
||||
root->addChild(coordinates);
|
||||
|
||||
auto drawStyle = new SoDrawStyle();
|
||||
drawStyle->lineWidth = 4.0;
|
||||
root->addChild(drawStyle);
|
||||
|
||||
auto lightModel = new SoLightModel();
|
||||
lightModel->model = SoLightModel::BASE_COLOR;
|
||||
root->addChild(lightModel);
|
||||
|
||||
auto lineSet = new SoLineSet();
|
||||
lineSet->numVertices.setValue(segments + 1);
|
||||
root->addChild(lineSet);
|
||||
@@ -478,7 +779,7 @@ SoGroup* RDragger::buildGeometry()
|
||||
root->addChild(sphereTranslation);
|
||||
|
||||
auto sphere = new SoSphere();
|
||||
sphere->radius.setValue(1.0);
|
||||
sphere->radius.setValue(0.8);
|
||||
root->addChild(sphere);
|
||||
|
||||
return root;
|
||||
@@ -656,6 +957,7 @@ SO_KIT_SOURCE(SoFCCSysDragger)
|
||||
void SoFCCSysDragger::initClass()
|
||||
{
|
||||
TDragger::initClass();
|
||||
TPlanarDragger::initClass();
|
||||
RDragger::initClass();
|
||||
SO_KIT_INIT_CLASS(SoFCCSysDragger, SoDragger, "Dragger");
|
||||
}
|
||||
@@ -668,6 +970,8 @@ SoFCCSysDragger::SoFCCSysDragger()
|
||||
SO_KIT_ADD_CATALOG_ENTRY(annotation, SoAnnotation, TRUE, geomSeparator, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(scaleNode, SoScale, TRUE, annotation, "", TRUE);
|
||||
|
||||
// Translator
|
||||
|
||||
SO_KIT_ADD_CATALOG_ENTRY(xTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(yTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(zTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE);
|
||||
@@ -688,6 +992,30 @@ SoFCCSysDragger::SoFCCSysDragger()
|
||||
SO_KIT_ADD_CATALOG_ENTRY(yTranslatorDragger, TDragger, TRUE, yTranslatorSeparator, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(zTranslatorDragger, TDragger, TRUE, zTranslatorSeparator, "", TRUE);
|
||||
|
||||
// Planar Translator
|
||||
|
||||
SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE);
|
||||
|
||||
SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorSeparator, SoSeparator, TRUE, xyPlanarTranslatorSwitch, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorSeparator, SoSeparator, TRUE, yzPlanarTranslatorSwitch, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorSeparator, SoSeparator, TRUE, zxPlanarTranslatorSwitch, "", TRUE);
|
||||
|
||||
SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorColor, SoBaseColor, TRUE, xyPlanarTranslatorSeparator, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorColor, SoBaseColor, TRUE, yzPlanarTranslatorSeparator, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorColor, SoBaseColor, TRUE, zxPlanarTranslatorSeparator, "", TRUE);
|
||||
|
||||
SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorRotation, SoRotation, TRUE, xyPlanarTranslatorSeparator, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorRotation, SoRotation, TRUE, yzPlanarTranslatorSeparator, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorRotation, SoRotation, TRUE, zxPlanarTranslatorSeparator, "", TRUE);
|
||||
|
||||
SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorDragger, TPlanarDragger, TRUE, xyPlanarTranslatorSeparator, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorDragger, TPlanarDragger, TRUE, yzPlanarTranslatorSeparator, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorDragger, TPlanarDragger, TRUE, zxPlanarTranslatorSeparator, "", TRUE);
|
||||
|
||||
// Rotator
|
||||
|
||||
SO_KIT_ADD_CATALOG_ENTRY(xRotatorSwitch, SoSwitch, TRUE, annotation, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(yRotatorSwitch, SoSwitch, TRUE, annotation, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(zRotatorSwitch, SoSwitch, TRUE, annotation, "", TRUE);
|
||||
@@ -708,6 +1036,8 @@ SoFCCSysDragger::SoFCCSysDragger()
|
||||
SO_KIT_ADD_CATALOG_ENTRY(yRotatorDragger, RDragger, TRUE, yRotatorSeparator, "", TRUE);
|
||||
SO_KIT_ADD_CATALOG_ENTRY(zRotatorDragger, RDragger, TRUE, zRotatorSeparator, "", TRUE);
|
||||
|
||||
// Other
|
||||
|
||||
SO_KIT_ADD_FIELD(translation, (0.0, 0.0, 0.0));
|
||||
SO_KIT_ADD_FIELD(translationIncrement, (1.0));
|
||||
SO_KIT_ADD_FIELD(translationIncrementCountX, (0));
|
||||
@@ -725,36 +1055,76 @@ SoFCCSysDragger::SoFCCSysDragger()
|
||||
|
||||
SO_KIT_INIT_INSTANCE();
|
||||
|
||||
SoBaseColor *color;
|
||||
color = SO_GET_ANY_PART(this, "xTranslatorColor", SoBaseColor);
|
||||
color->rgb.setValue(1.0, 0.0, 0.0);
|
||||
color = SO_GET_ANY_PART(this, "yTranslatorColor", SoBaseColor);
|
||||
color->rgb.setValue(0.0, 1.0, 0.0);
|
||||
color = SO_GET_ANY_PART(this, "zTranslatorColor", SoBaseColor);
|
||||
color->rgb.setValue(0.0, 0.0, 1.0);
|
||||
color = SO_GET_ANY_PART(this, "xRotatorColor", SoBaseColor);
|
||||
color->rgb.setValue(1.0, 0.0, 0.0);
|
||||
color = SO_GET_ANY_PART(this, "yRotatorColor", SoBaseColor);
|
||||
color->rgb.setValue(0.0, 1.0, 0.0);
|
||||
color = SO_GET_ANY_PART(this, "zRotatorColor", SoBaseColor);
|
||||
color->rgb.setValue(0.0, 0.0, 1.0);
|
||||
// Colors
|
||||
|
||||
SoBaseColor *color;
|
||||
App::Color stdColor;
|
||||
auto viewParams = Gui::ViewParams::instance();
|
||||
// Translator
|
||||
color = SO_GET_ANY_PART(this, "xTranslatorColor", SoBaseColor);
|
||||
stdColor.setPackedValue(viewParams->getAxisXColor());
|
||||
color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b);
|
||||
color = SO_GET_ANY_PART(this, "yTranslatorColor", SoBaseColor);
|
||||
stdColor.setPackedValue(viewParams->getAxisYColor());
|
||||
color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b);
|
||||
color = SO_GET_ANY_PART(this, "zTranslatorColor", SoBaseColor);
|
||||
stdColor.setPackedValue(viewParams->getAxisZColor());
|
||||
color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b);
|
||||
// Planar Translator
|
||||
color = SO_GET_ANY_PART(this, "xyPlanarTranslatorColor", SoBaseColor);
|
||||
stdColor.setPackedValue(viewParams->getAxisZColor());
|
||||
color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b);
|
||||
color = SO_GET_ANY_PART(this, "yzPlanarTranslatorColor", SoBaseColor);
|
||||
stdColor.setPackedValue(viewParams->getAxisXColor());
|
||||
color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b);
|
||||
color = SO_GET_ANY_PART(this, "zxPlanarTranslatorColor", SoBaseColor);
|
||||
stdColor.setPackedValue(viewParams->getAxisYColor());
|
||||
color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b);
|
||||
// Rotator
|
||||
color = SO_GET_ANY_PART(this, "xRotatorColor", SoBaseColor);
|
||||
stdColor.setPackedValue(viewParams->getAxisXAltColor());
|
||||
color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b);
|
||||
color = SO_GET_ANY_PART(this, "yRotatorColor", SoBaseColor);
|
||||
stdColor.setPackedValue(viewParams->getAxisYAltColor());
|
||||
color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b);
|
||||
color = SO_GET_ANY_PART(this, "zRotatorColor", SoBaseColor);
|
||||
stdColor.setPackedValue(viewParams->getAxisZAltColor());
|
||||
color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b);
|
||||
|
||||
// Increments
|
||||
|
||||
// Translator
|
||||
TDragger *tDragger;
|
||||
tDragger = SO_GET_ANY_PART(this, "xTranslatorDragger", TDragger);
|
||||
tDragger->translationIncrement.connectFrom(&this->translationIncrement);
|
||||
tDragger->autoScaleResult.connectFrom(&this->autoScaleResult);
|
||||
translationIncrementCountX.connectFrom(&tDragger->translationIncrementCount);
|
||||
|
||||
tDragger = SO_GET_ANY_PART(this, "yTranslatorDragger", TDragger);
|
||||
tDragger->translationIncrement.connectFrom(&this->translationIncrement);
|
||||
tDragger->autoScaleResult.connectFrom(&this->autoScaleResult);
|
||||
translationIncrementCountY.connectFrom(&tDragger->translationIncrementCount);
|
||||
|
||||
tDragger = SO_GET_ANY_PART(this, "zTranslatorDragger", TDragger);
|
||||
tDragger->translationIncrement.connectFrom(&this->translationIncrement);
|
||||
tDragger->autoScaleResult.connectFrom(&this->autoScaleResult);
|
||||
translationIncrementCountZ.connectFrom(&tDragger->translationIncrementCount);
|
||||
|
||||
// Planar Translator
|
||||
TPlanarDragger *tPlanarDragger;
|
||||
tPlanarDragger = SO_GET_ANY_PART(this, "xyPlanarTranslatorDragger", TPlanarDragger);
|
||||
tPlanarDragger->translationIncrement.connectFrom(&this->translationIncrement);
|
||||
tPlanarDragger->autoScaleResult.connectFrom(&this->autoScaleResult);
|
||||
translationIncrementCountX.appendConnection(&tPlanarDragger->translationIncrementXCount);
|
||||
translationIncrementCountY.appendConnection(&tPlanarDragger->translationIncrementYCount);
|
||||
tPlanarDragger = SO_GET_ANY_PART(this, "yzPlanarTranslatorDragger", TPlanarDragger);
|
||||
tPlanarDragger->translationIncrement.connectFrom(&this->translationIncrement);
|
||||
tPlanarDragger->autoScaleResult.connectFrom(&this->autoScaleResult);
|
||||
translationIncrementCountZ.appendConnection(&tPlanarDragger->translationIncrementXCount);
|
||||
translationIncrementCountY.appendConnection(&tPlanarDragger->translationIncrementYCount);
|
||||
tPlanarDragger = SO_GET_ANY_PART(this, "zxPlanarTranslatorDragger", TPlanarDragger);
|
||||
tPlanarDragger->translationIncrement.connectFrom(&this->translationIncrement);
|
||||
tPlanarDragger->autoScaleResult.connectFrom(&this->autoScaleResult);
|
||||
translationIncrementCountX.appendConnection(&tPlanarDragger->translationIncrementXCount);
|
||||
translationIncrementCountZ.appendConnection(&tPlanarDragger->translationIncrementYCount);
|
||||
// Rotator
|
||||
RDragger *rDragger;
|
||||
rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", RDragger);
|
||||
rDragger->rotationIncrement.connectFrom(&this->rotationIncrement);
|
||||
@@ -766,12 +1136,23 @@ SoFCCSysDragger::SoFCCSysDragger()
|
||||
rDragger->rotationIncrement.connectFrom(&this->rotationIncrement);
|
||||
rotationIncrementCountZ.connectFrom(&rDragger->rotationIncrementCount);
|
||||
|
||||
// Switches
|
||||
|
||||
// Translator
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
// Planar Translator
|
||||
sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
// Rotator
|
||||
sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch);
|
||||
@@ -779,26 +1160,34 @@ SoFCCSysDragger::SoFCCSysDragger()
|
||||
sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
|
||||
// Rotations
|
||||
|
||||
SoRotation *localRotation;
|
||||
SbRotation tempRotation;
|
||||
auto angle = static_cast<float>(M_PI / 2.0);
|
||||
// Translator
|
||||
localRotation = SO_GET_ANY_PART(this, "xTranslatorRotation", SoRotation);
|
||||
localRotation->rotation.setValue(SbVec3f(0.0, 0.0, -1.0), angle);
|
||||
localRotation = SO_GET_ANY_PART(this, "yTranslatorRotation", SoRotation);
|
||||
localRotation->rotation.setValue(SbRotation::identity());
|
||||
localRotation = SO_GET_ANY_PART(this, "zTranslatorRotation", SoRotation);
|
||||
localRotation->rotation.setValue(SbVec3f(1.0, 0.0, 0.0), angle);
|
||||
|
||||
// Planar Translator
|
||||
localRotation = SO_GET_ANY_PART(this, "xyPlanarTranslatorRotation", SoRotation);
|
||||
localRotation->rotation.setValue(SbRotation::identity());
|
||||
localRotation = SO_GET_ANY_PART(this, "yzPlanarTranslatorRotation", SoRotation);
|
||||
localRotation->rotation.setValue(SbVec3f(0.0, -1.0, 0.0), angle);
|
||||
localRotation = SO_GET_ANY_PART(this, "zxPlanarTranslatorRotation", SoRotation);
|
||||
localRotation->rotation.setValue(SbVec3f(1.0, 0.0, 0.0), angle);
|
||||
// Rotator
|
||||
localRotation = SO_GET_ANY_PART(this, "xRotatorRotation", SoRotation);
|
||||
tempRotation = SbRotation(SbVec3f(1.0, 0.0, 0.0), angle);
|
||||
tempRotation *= SbRotation(SbVec3f(0.0, 0.0, 1.0), angle);
|
||||
localRotation->rotation.setValue(tempRotation);
|
||||
|
||||
localRotation = SO_GET_ANY_PART(this, "yRotatorRotation", SoRotation);
|
||||
tempRotation = SbRotation(SbVec3f(0.0, -1.0, 0.0), angle);
|
||||
tempRotation *= SbRotation(SbVec3f(0.0, 0.0, -1.0), angle);
|
||||
localRotation->rotation.setValue(tempRotation);
|
||||
|
||||
localRotation = SO_GET_ANY_PART(this, "zRotatorRotation", SoRotation);
|
||||
localRotation->rotation.setValue(SbRotation::identity());
|
||||
|
||||
@@ -857,6 +1246,9 @@ SbBool SoFCCSysDragger::setUpConnections(SbBool onoff, SbBool doitalways)
|
||||
TDragger *tDraggerX = SO_GET_ANY_PART(this, "xTranslatorDragger", TDragger);
|
||||
TDragger *tDraggerY = SO_GET_ANY_PART(this, "yTranslatorDragger", TDragger);
|
||||
TDragger *tDraggerZ = SO_GET_ANY_PART(this, "zTranslatorDragger", TDragger);
|
||||
TPlanarDragger *tPlanarDraggerXZ = SO_GET_ANY_PART(this, "xyPlanarTranslatorDragger", TPlanarDragger);
|
||||
TPlanarDragger *tPlanarDraggerYZ = SO_GET_ANY_PART(this, "yzPlanarTranslatorDragger", TPlanarDragger);
|
||||
TPlanarDragger *tPlanarDraggerZX = SO_GET_ANY_PART(this, "zxPlanarTranslatorDragger", TPlanarDragger);
|
||||
RDragger *rDraggerX = SO_GET_ANY_PART(this, "xRotatorDragger", RDragger);
|
||||
RDragger *rDraggerY = SO_GET_ANY_PART(this, "yRotatorDragger", RDragger);
|
||||
RDragger *rDraggerZ = SO_GET_ANY_PART(this, "zRotatorDragger", RDragger);
|
||||
@@ -868,6 +1260,9 @@ SbBool SoFCCSysDragger::setUpConnections(SbBool onoff, SbBool doitalways)
|
||||
registerChildDragger(tDraggerX);
|
||||
registerChildDragger(tDraggerY);
|
||||
registerChildDragger(tDraggerZ);
|
||||
registerChildDragger(tPlanarDraggerXZ);
|
||||
registerChildDragger(tPlanarDraggerYZ);
|
||||
registerChildDragger(tPlanarDraggerZX);
|
||||
registerChildDragger(rDraggerX);
|
||||
registerChildDragger(rDraggerY);
|
||||
registerChildDragger(rDraggerZ);
|
||||
@@ -885,6 +1280,9 @@ SbBool SoFCCSysDragger::setUpConnections(SbBool onoff, SbBool doitalways)
|
||||
unregisterChildDragger(tDraggerX);
|
||||
unregisterChildDragger(tDraggerY);
|
||||
unregisterChildDragger(tDraggerZ);
|
||||
unregisterChildDragger(tPlanarDraggerXZ);
|
||||
unregisterChildDragger(tPlanarDraggerYZ);
|
||||
unregisterChildDragger(tPlanarDraggerZX);
|
||||
unregisterChildDragger(rDraggerX);
|
||||
unregisterChildDragger(rDraggerY);
|
||||
unregisterChildDragger(rDraggerZ);
|
||||
@@ -1070,18 +1468,19 @@ void SoFCCSysDragger::clearIncrementCounts()
|
||||
rotationIncrementCountZ.setValue(0);
|
||||
}
|
||||
|
||||
// Visiblity API Functions
|
||||
|
||||
// Translator
|
||||
void SoFCCSysDragger::showTranslationX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::showTranslationY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::showTranslationZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch);
|
||||
@@ -1093,31 +1492,125 @@ void SoFCCSysDragger::hideTranslationX()
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::hideTranslationY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::hideTranslationZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isShownTranslationX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
bool SoFCCSysDragger::isShownTranslationY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
bool SoFCCSysDragger::isShownTranslationZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isHiddenTranslationX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_NONE);
|
||||
}
|
||||
bool SoFCCSysDragger::isHiddenTranslationY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_NONE);
|
||||
}
|
||||
bool SoFCCSysDragger::isHiddenTranslationZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
// Planar Translator
|
||||
void SoFCCSysDragger::showPlanarTranslationXY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
}
|
||||
void SoFCCSysDragger::showPlanarTranslationYZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
}
|
||||
void SoFCCSysDragger::showPlanarTranslationZX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::hidePlanarTranslationXY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
|
||||
}
|
||||
void SoFCCSysDragger::hidePlanarTranslationYZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
|
||||
}
|
||||
void SoFCCSysDragger::hidePlanarTranslationZX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isShownPlanarTranslationXY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
bool SoFCCSysDragger::isShownPlanarTranslationYZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
bool SoFCCSysDragger::isShownPlanarTranslationZX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isHiddenPlanarTranslationXY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_NONE);
|
||||
}
|
||||
bool SoFCCSysDragger::isHiddenPlanarTranslationYZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_NONE);
|
||||
}
|
||||
bool SoFCCSysDragger::isHiddenPlanarTranslationZX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
// Rotator
|
||||
void SoFCCSysDragger::showRotationX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::showRotationY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::showRotationZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch);
|
||||
@@ -1129,85 +1622,43 @@ void SoFCCSysDragger::hideRotationX()
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::hideRotationY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
void SoFCCSysDragger::hideRotationZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch);
|
||||
SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isShownTranslationX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isShownTranslationY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isShownTranslationZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isShownRotationX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isShownRotationY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isShownRotationZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_ALL);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isHiddenTranslationX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isHiddenTranslationY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isHiddenTranslationZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isHiddenRotationX()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isHiddenRotationY()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch);
|
||||
return (sw->whichChild.getValue() == SO_SWITCH_NONE);
|
||||
}
|
||||
|
||||
bool SoFCCSysDragger::isHiddenRotationZ()
|
||||
{
|
||||
SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch);
|
||||
|
||||
@@ -86,6 +86,56 @@ private:
|
||||
using inherited = SoDragger;
|
||||
};
|
||||
|
||||
/*! @brief Planar Translation Dragger.
|
||||
*
|
||||
* used for translating on a plane. Set the
|
||||
* translationIncrement to desired step. Use
|
||||
* 'translationIncrementXCount' or
|
||||
* 'translationIncrementYCount' multiplied with
|
||||
* 'translationIncrement' for a full double
|
||||
* precision vector scalar.
|
||||
*
|
||||
* @author qewer33
|
||||
*/
|
||||
class TPlanarDragger : public SoDragger
|
||||
{
|
||||
SO_KIT_HEADER(TDragger);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(planarTranslatorSwitch);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(planarTranslator);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(planarTranslatorActive);
|
||||
public:
|
||||
static void initClass();
|
||||
TPlanarDragger();
|
||||
SoSFVec3f translation; //!< set from outside and used from outside for single precision.
|
||||
SoSFDouble translationIncrement; //!< set from outside and used for rounding.
|
||||
SoSFInt32 translationIncrementXCount; //!< number of steps. used from outside.
|
||||
SoSFInt32 translationIncrementYCount; //!< number of steps. used from outside.
|
||||
SoSFFloat autoScaleResult; //!< set from parent dragger.
|
||||
|
||||
protected:
|
||||
~TPlanarDragger() override;
|
||||
SbBool setUpConnections(SbBool onoff, SbBool doitalways = FALSE) override;
|
||||
|
||||
static void startCB(void *, SoDragger * d);
|
||||
static void motionCB(void *, SoDragger * d);
|
||||
static void finishCB(void *, SoDragger * d);
|
||||
static void fieldSensorCB(void *f, SoSensor *);
|
||||
static void valueChangedCB(void *, SoDragger *d);
|
||||
|
||||
void dragStart();
|
||||
void drag();
|
||||
void dragFinish();
|
||||
|
||||
SoFieldSensor fieldSensor;
|
||||
SbPlaneProjector projector;
|
||||
|
||||
private:
|
||||
void buildFirstInstance();
|
||||
SbVec3f roundTranslation(const SbVec3f &vecIn, float incrementIn);
|
||||
SoGroup* buildGeometry();
|
||||
using inherited = SoDragger;
|
||||
};
|
||||
|
||||
/*! @brief Rotation Dragger.
|
||||
*
|
||||
* used for rotating around an axis. Set the rotation
|
||||
@@ -149,6 +199,7 @@ class GuiExport SoFCCSysDragger : public SoDragger
|
||||
SO_KIT_HEADER(SoFCCSysDragger);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(annotation);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(scaleNode);
|
||||
// Translator
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(xTranslatorSwitch);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(yTranslatorSwitch);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(zTranslatorSwitch);
|
||||
@@ -164,6 +215,23 @@ class GuiExport SoFCCSysDragger : public SoDragger
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(xTranslatorDragger);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(yTranslatorDragger);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(zTranslatorDragger);
|
||||
// Planar Translator
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(xyPlanarTranslatorSwitch);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(yzPlanarTranslatorSwitch);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(zxPlanarTranslatorSwitch);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(xyPlanarTranslatorSeparator);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(yzPlanarTranslatorSeparator);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(zxPlanarTranslatorSeparator);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(xyPlanarTranslatorColor);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(yzPlanarTranslatorColor);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(zxPlanarTranslatorColor);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(xyPlanarTranslatorRotation);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(yzPlanarTranslatorRotation);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(zxPlanarTranslatorRotation);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(xyPlanarTranslatorDragger);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(yzPlanarTranslatorDragger);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(zxPlanarTranslatorDragger);
|
||||
// Rotator
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(xRotatorSwitch);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(yRotatorSwitch);
|
||||
SO_KIT_CATALOG_ENTRY_HEADER(zRotatorSwitch);
|
||||
@@ -218,6 +286,25 @@ public:
|
||||
void hideTranslationX(); //!< hide the x translation dragger.
|
||||
void hideTranslationY(); //!< hide the y translation dragger.
|
||||
void hideTranslationZ(); //!< hide the z translation dragger.
|
||||
bool isShownTranslationX(); //!< is x translation dragger shown.
|
||||
bool isShownTranslationY(); //!< is y translation dragger shown.
|
||||
bool isShownTranslationZ(); //!< is z translation dragger shown.
|
||||
bool isHiddenTranslationX(); //!< is x translation dragger hidden.
|
||||
bool isHiddenTranslationY(); //!< is y translation dragger hidden.
|
||||
bool isHiddenTranslationZ(); //!< is z translation dragger hidden.
|
||||
|
||||
void showPlanarTranslationXY(); //!< show the xy planar translation dragger.
|
||||
void showPlanarTranslationYZ(); //!< show the yz planar translation dragger.
|
||||
void showPlanarTranslationZX(); //!< show the zx planar translation dragger.
|
||||
void hidePlanarTranslationXY(); //!< hide the xy planar translation dragger.
|
||||
void hidePlanarTranslationYZ(); //!< hide the yz planar translation dragger.
|
||||
void hidePlanarTranslationZX(); //!< hide the zx planar translation dragger.
|
||||
bool isShownPlanarTranslationXY(); //!< is xy planar translation dragger shown.
|
||||
bool isShownPlanarTranslationYZ(); //!< is yz planar translation dragger shown.
|
||||
bool isShownPlanarTranslationZX(); //!< is zx planar translation dragger shown.
|
||||
bool isHiddenPlanarTranslationXY(); //!< is xy planar translation dragger hidden.
|
||||
bool isHiddenPlanarTranslationYZ(); //!< is yz planar translation dragger hidden.
|
||||
bool isHiddenPlanarTranslationZX(); //!< is zx planar translation dragger hidden.
|
||||
|
||||
void showRotationX(); //!< show the x rotation dragger.
|
||||
void showRotationY(); //!< show the y rotation dragger.
|
||||
@@ -225,17 +312,9 @@ public:
|
||||
void hideRotationX(); //!< hide the x rotation dragger.
|
||||
void hideRotationY(); //!< hide the y rotation dragger.
|
||||
void hideRotationZ(); //!< hide the z rotation dragger.
|
||||
|
||||
bool isShownTranslationX(); //!< is x translation dragger shown.
|
||||
bool isShownTranslationY(); //!< is y translation dragger shown.
|
||||
bool isShownTranslationZ(); //!< is z translation dragger shown.
|
||||
bool isShownRotationX(); //!< is x rotation dragger shown.
|
||||
bool isShownRotationY(); //!< is x rotation dragger shown.
|
||||
bool isShownRotationZ(); //!< is x rotation dragger shown.
|
||||
|
||||
bool isHiddenTranslationX(); //!< is x translation dragger hidden.
|
||||
bool isHiddenTranslationY(); //!< is y translation dragger hidden.
|
||||
bool isHiddenTranslationZ(); //!< is z translation dragger hidden.
|
||||
bool isHiddenRotationX(); //!< is x rotation dragger hidden.
|
||||
bool isHiddenRotationY(); //!< is x rotation dragger hidden.
|
||||
bool isHiddenRotationZ(); //!< is x rotation dragger hidden.
|
||||
|
||||
@@ -33,16 +33,12 @@
|
||||
# include <Inventor/events/SoButtonEvent.h>
|
||||
# include <Inventor/events/SoMouseButtonEvent.h>
|
||||
# include <Inventor/events/SoKeyboardEvent.h>
|
||||
# include <Inventor/sensors/SoNodeSensor.h>
|
||||
# include <Inventor/nodes/SoOrthographicCamera.h>
|
||||
# include <Inventor/nodes/SoBaseColor.h>
|
||||
# include <Inventor/nodes/SoCoordinate3.h>
|
||||
# include <Inventor/nodes/SoLineSet.h>
|
||||
# include <Inventor/nodes/SoAnnotation.h>
|
||||
# include <Inventor/nodes/SoTransform.h>
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
#include <Gui/View3DInventor.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
// clang-format on
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Precision.h>
|
||||
@@ -54,6 +50,7 @@
|
||||
#include <Gui/Camera.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/SoDatumLabel.h>
|
||||
#include <Gui/EditableDatumLabel.h>
|
||||
|
||||
#include <Gui/ViewProviderDocumentObject.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
@@ -77,6 +74,7 @@ TaskImage::TaskImage(Image::ImagePlane* obj, QWidget* parent)
|
||||
|
||||
initialiseTransparency();
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
aspectRatio = obj->XSize.getValue() / obj->YSize.getValue();
|
||||
|
||||
connectSignals();
|
||||
@@ -129,6 +127,7 @@ void TaskImage::connectSignals()
|
||||
|
||||
void TaskImage::initialiseTransparency()
|
||||
{
|
||||
// NOLINTBEGIN
|
||||
auto vp = Application::Instance->getViewProvider(feature.get());
|
||||
App::Property* prop = vp->getPropertyByName("Transparency");
|
||||
if (prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) {
|
||||
@@ -136,17 +135,18 @@ void TaskImage::initialiseTransparency()
|
||||
ui->spinBoxTransparency->setValue(Transparency->getValue());
|
||||
ui->sliderTransparency->setValue(Transparency->getValue());
|
||||
}
|
||||
// NOLINTEND
|
||||
}
|
||||
|
||||
void TaskImage::changeTransparency(int val)
|
||||
{
|
||||
if (feature.expired())
|
||||
if (feature.expired()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto vp = Application::Instance->getViewProvider(feature.get());
|
||||
App::Property* prop = vp->getPropertyByName("Transparency");
|
||||
if (prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) {
|
||||
auto Transparency = static_cast<App::PropertyInteger*>(prop);
|
||||
if (auto Transparency = dynamic_cast<App::PropertyInteger*>(prop)) {
|
||||
Transparency->setValue(val);
|
||||
|
||||
QSignalBlocker block(ui->spinBoxTransparency);
|
||||
@@ -184,7 +184,7 @@ View3DInventorViewer* TaskImage::getViewer() const
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
auto vp = Application::Instance->getViewProvider(feature.get());
|
||||
auto doc = static_cast<ViewProviderDocumentObject*>(vp)->getDocument();
|
||||
auto doc = static_cast<ViewProviderDocumentObject*>(vp)->getDocument(); // NOLINT
|
||||
auto view = dynamic_cast<View3DInventor*>(doc->getViewOfViewProvider(vp));
|
||||
if (view) {
|
||||
return view->getViewer();
|
||||
@@ -285,47 +285,45 @@ void TaskImage::onPreview()
|
||||
updatePlacement();
|
||||
}
|
||||
|
||||
void TaskImage::restore(const Base::Placement& plm)
|
||||
// NOLINTNEXTLINE
|
||||
void TaskImage::restoreAngles(const Base::Rotation& rot)
|
||||
{
|
||||
if (feature.expired())
|
||||
return;
|
||||
|
||||
QSignalBlocker blockW(ui->spinBoxWidth);
|
||||
QSignalBlocker blockH(ui->spinBoxHeight);
|
||||
ui->spinBoxWidth->setValue(feature->XSize.getValue());
|
||||
ui->spinBoxHeight->setValue(feature->YSize.getValue());
|
||||
|
||||
Base::Rotation rot = plm.getRotation();
|
||||
Base::Vector3d pos = plm.getPosition();
|
||||
|
||||
double yaw, pitch, roll;
|
||||
double yaw{};
|
||||
double pitch{};
|
||||
double roll{};
|
||||
rot.getYawPitchRoll(yaw, pitch, roll);
|
||||
|
||||
double tol = 1.0e-5;
|
||||
bool reverse = false;
|
||||
|
||||
const double tol = 1.0e-5;
|
||||
const double angle1 = 90.0;
|
||||
const double angle2 = 180.0;
|
||||
|
||||
auto isTopOrBottom = [=](bool& reverse) {
|
||||
if (fabs(pitch) < tol && (fabs(roll) < tol || fabs(roll - 180.) < tol)) {
|
||||
if (fabs(roll - 180.) < tol)
|
||||
if (fabs(pitch) < tol && (fabs(roll) < tol || fabs(roll - angle2) < tol)) {
|
||||
if (fabs(roll - angle2) < tol) {
|
||||
reverse = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
auto isFrontOrRear = [=](bool& reverse) {
|
||||
if (fabs(roll - 90.) < tol && (fabs(yaw) < tol || fabs(yaw - 180.) < tol)) {
|
||||
if (fabs(yaw - 180.) < tol)
|
||||
if (fabs(roll - angle1) < tol && (fabs(yaw) < tol || fabs(yaw - angle2) < tol)) {
|
||||
if (fabs(yaw - angle2) < tol) {
|
||||
reverse = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
auto isRightOrLeft = [=](bool& reverse) {
|
||||
if (fabs(roll - 90.) < tol && (fabs(yaw - 90.) < tol || fabs(yaw + 90.) < tol)) {
|
||||
if (fabs(yaw + 90.) < tol)
|
||||
if (fabs(roll - angle1) < tol && (fabs(yaw - angle1) < tol || fabs(yaw + angle1) < tol)) {
|
||||
if (fabs(yaw + angle1) < tol) {
|
||||
reverse = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -346,8 +344,27 @@ void TaskImage::restore(const Base::Placement& plm)
|
||||
ui->spinBoxRotation->setValue(-pitch);
|
||||
}
|
||||
ui->Reverse_checkBox->setChecked(reverse);
|
||||
}
|
||||
|
||||
Base::Vector3d R0(0, 0, 0), RX(1, 0, 0), RY(0, 1, 0);
|
||||
void TaskImage::restore(const Base::Placement& plm)
|
||||
{
|
||||
if (feature.expired()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QSignalBlocker blockW(ui->spinBoxWidth);
|
||||
QSignalBlocker blockH(ui->spinBoxHeight);
|
||||
ui->spinBoxWidth->setValue(feature->XSize.getValue());
|
||||
ui->spinBoxHeight->setValue(feature->YSize.getValue());
|
||||
|
||||
Base::Rotation rot = plm.getRotation(); // NOLINT
|
||||
Base::Vector3d pos = plm.getPosition();
|
||||
|
||||
restoreAngles(rot);
|
||||
|
||||
Base::Vector3d R0(0, 0, 0);
|
||||
Base::Vector3d RX(1, 0, 0);
|
||||
Base::Vector3d RY(0, 1, 0);
|
||||
|
||||
RX = rot.multVec(RX);
|
||||
RY = rot.multVec(RY);
|
||||
@@ -364,6 +381,7 @@ void TaskImage::updatePlacement()
|
||||
double angle = ui->spinBoxRotation->value().getValue();
|
||||
bool reverse = ui->Reverse_checkBox->isChecked();
|
||||
|
||||
// NOLINTBEGIN
|
||||
Base::Placement Pos;
|
||||
Base::Rotation rot;
|
||||
double dir = reverse ? 180. : 0.;
|
||||
@@ -378,6 +396,7 @@ void TaskImage::updatePlacement()
|
||||
else if (ui->YZ_radioButton->isChecked()) {
|
||||
rot.setYawPitchRoll(90. - dir, -angle, 90.);
|
||||
}
|
||||
// NOLINTEND
|
||||
|
||||
Base::Vector3d offset = Base::Vector3d(ui->spinBoxX->value().getValue(), ui->spinBoxY->value().getValue(), ui->spinBoxZ->value().getValue());
|
||||
offset = rot.multVec(offset);
|
||||
@@ -385,8 +404,9 @@ void TaskImage::updatePlacement()
|
||||
|
||||
if (!feature.expired()) {
|
||||
feature->Placement.setValue(Pos);
|
||||
if(scale)
|
||||
if (scale) {
|
||||
scale->setPlacement(feature->globalPlacement());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,69 +431,26 @@ void TaskImage::updateIcon()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
struct NodeData {
|
||||
InteractiveScale* scale;
|
||||
};
|
||||
|
||||
InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, Base::Placement plc)
|
||||
InteractiveScale::InteractiveScale(View3DInventorViewer* view,
|
||||
ViewProvider* vp,
|
||||
const Base::Placement& plc) // NOLINT
|
||||
: active(false)
|
||||
, placement(plc)
|
||||
, viewer(view)
|
||||
, viewProv(vp)
|
||||
, midPoint(SbVec3f(0,0,0))
|
||||
{
|
||||
root = new SoAnnotation;
|
||||
root->ref();
|
||||
root->renderCaching = SoSeparator::OFF;
|
||||
|
||||
measureLabel = new SoDatumLabel();
|
||||
measureLabel->ref();
|
||||
measureLabel->string = "";
|
||||
measureLabel->textColor = SbColor(1.0f, 0.149f, 0.0f);
|
||||
measureLabel->size.setValue(17);
|
||||
measureLabel->lineWidth = 2.0;
|
||||
measureLabel->useAntialiasing = false;
|
||||
measureLabel->param1 = 0.;
|
||||
measureLabel->param2 = 0.;
|
||||
|
||||
transform = new SoTransform();
|
||||
root->addChild(transform);
|
||||
setPlacement(placement);
|
||||
|
||||
QWidget* mdi = view->parentWidget();
|
||||
|
||||
distanceBox = new QuantitySpinBox(mdi);
|
||||
distanceBox->setUnit(Base::Unit::Length);
|
||||
distanceBox->setMinimum(0.0);
|
||||
distanceBox->setMaximum(INT_MAX);
|
||||
distanceBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||
distanceBox->setToolTip(tr("Enter desired distance between the points"));
|
||||
distanceBox->setKeyboardTracking(false);
|
||||
distanceBox->installEventFilter(this);
|
||||
|
||||
//track camera movements to update spinbox position.
|
||||
NodeData* info = new NodeData{ this };
|
||||
cameraSensor = new SoNodeSensor([](void* data, SoSensor* sensor) {
|
||||
Q_UNUSED(sensor)
|
||||
NodeData* info = static_cast<NodeData*>(data);
|
||||
info->scale->positionWidget();
|
||||
}, info);
|
||||
cameraSensor->attach(viewer->getCamera());
|
||||
measureLabel = new EditableDatumLabel(viewer, placement, SbColor(1.0F, 0.149F, 0.0F)); //NOLINT
|
||||
}
|
||||
|
||||
InteractiveScale::~InteractiveScale()
|
||||
{
|
||||
root->unref();
|
||||
measureLabel->unref();
|
||||
distanceBox->deleteLater();
|
||||
cameraSensor->detach();
|
||||
delete measureLabel;
|
||||
}
|
||||
|
||||
void InteractiveScale::activate()
|
||||
{
|
||||
if (viewer) {
|
||||
static_cast<SoSeparator*>(viewer->getSceneGraph())->addChild(root);
|
||||
viewer->setEditing(true);
|
||||
viewer->addEventCallback(SoLocation2Event::getClassTypeId(), InteractiveScale::getMousePosition, this);
|
||||
viewer->addEventCallback(SoButtonEvent::getClassTypeId(), InteractiveScale::soEventFilter, this);
|
||||
@@ -486,10 +463,8 @@ void InteractiveScale::activate()
|
||||
void InteractiveScale::deactivate()
|
||||
{
|
||||
if (viewer) {
|
||||
distanceBox->hide();
|
||||
points.clear();
|
||||
root->removeChild(measureLabel);
|
||||
static_cast<SoSeparator*>(viewer->getSceneGraph())->removeChild(root);
|
||||
measureLabel->deactivate();
|
||||
viewer->setEditing(false);
|
||||
viewer->removeEventCallback(SoLocation2Event::getClassTypeId(), InteractiveScale::getMousePosition, this);
|
||||
viewer->removeEventCallback(SoButtonEvent::getClassTypeId(), InteractiveScale::soEventFilter, this);
|
||||
@@ -501,16 +476,18 @@ void InteractiveScale::deactivate()
|
||||
|
||||
double InteractiveScale::getScaleFactor() const
|
||||
{
|
||||
if ((points[0] - points[1]).length() == 0.)
|
||||
if ((points[0] - points[1]).length() == 0.) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
return distanceBox->value().getValue() / (points[0] - points[1]).length();
|
||||
return measureLabel->getValue() / (points[0] - points[1]).length();
|
||||
}
|
||||
|
||||
double InteractiveScale::getDistance(const SbVec3f& pt) const
|
||||
{
|
||||
if (points.empty())
|
||||
if (points.empty()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return (points[0] - pt).length();
|
||||
}
|
||||
@@ -522,19 +499,20 @@ void InteractiveScale::setDistance(const SbVec3f& pos3d)
|
||||
quantity.setUnit(Base::Unit::Length);
|
||||
|
||||
//Update the displayed distance
|
||||
double factor;
|
||||
QString unitStr, valueStr;
|
||||
double factor{};
|
||||
QString unitStr;
|
||||
QString valueStr;
|
||||
valueStr = quantity.getUserString(factor, unitStr);
|
||||
measureLabel->string = SbString(valueStr.toUtf8().constData());
|
||||
measureLabel->setPoints(getCoordsOnImagePlane(points[0]), getCoordsOnImagePlane(pos3d));
|
||||
measureLabel->label->string = SbString(valueStr.toUtf8().constData());
|
||||
measureLabel->label->setPoints(getCoordsOnImagePlane(points[0]), getCoordsOnImagePlane(pos3d));
|
||||
}
|
||||
|
||||
void InteractiveScale::findPointOnImagePlane(SoEventCallback * ecb)
|
||||
{
|
||||
const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent *>(ecb->getEvent());
|
||||
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(ecb->getUserData());
|
||||
const SoEvent * mbe = ecb->getEvent();
|
||||
auto view = static_cast<Gui::View3DInventorViewer*>(ecb->getUserData());
|
||||
std::unique_ptr<SoPickedPoint> pp(view->getPointOnRay(mbe->getPosition(), viewProv));
|
||||
if (pp.get()) {
|
||||
if (pp) {
|
||||
auto pos3d = pp->getPoint();
|
||||
|
||||
collectPoint(pos3d);
|
||||
@@ -546,8 +524,8 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d)
|
||||
if (points.empty()) {
|
||||
points.push_back(pos3d);
|
||||
|
||||
measureLabel->setPoints(getCoordsOnImagePlane(pos3d), getCoordsOnImagePlane(pos3d));
|
||||
root->addChild(measureLabel);
|
||||
measureLabel->label->setPoints(getCoordsOnImagePlane(pos3d), getCoordsOnImagePlane(pos3d));
|
||||
measureLabel->activate();
|
||||
}
|
||||
else if (points.size() == 1) {
|
||||
double distance = getDistance(pos3d);
|
||||
@@ -556,8 +534,7 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d)
|
||||
|
||||
midPoint = (points[0] + points[1]) / 2;
|
||||
|
||||
measureLabel->string = "";
|
||||
showDistanceField();
|
||||
measureLabel->startEdit(getDistance(points[1]), this);
|
||||
|
||||
Q_EMIT enableApplyBtn();
|
||||
}
|
||||
@@ -567,37 +544,17 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d)
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveScale::showDistanceField()
|
||||
{
|
||||
distanceBox->show();
|
||||
QSignalBlocker block(distanceBox);
|
||||
distanceBox->setValue(getDistance(points[1]));
|
||||
distanceBox->adjustSize();
|
||||
positionWidget();
|
||||
distanceBox->selectNumber();
|
||||
distanceBox->setFocus();
|
||||
}
|
||||
|
||||
void InteractiveScale::positionWidget()
|
||||
{
|
||||
QSize wSize = distanceBox->size();
|
||||
QPoint pxCoord = viewer->toQPoint(viewer->getPointOnViewport(midPoint));
|
||||
pxCoord.setX(std::max(pxCoord.x() - wSize.width() / 2, 0));
|
||||
pxCoord.setY(std::max(pxCoord.y() - wSize.height() / 2, 0));
|
||||
distanceBox->move(pxCoord);
|
||||
}
|
||||
|
||||
void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb)
|
||||
{
|
||||
InteractiveScale* scale = static_cast<InteractiveScale*>(ud);
|
||||
const SoLocation2Event * l2e = static_cast<const SoLocation2Event *>(ecb->getEvent());
|
||||
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(ecb->getUserData());
|
||||
auto scale = static_cast<InteractiveScale*>(ud);
|
||||
const SoEvent* l2e = ecb->getEvent();
|
||||
auto view = static_cast<Gui::View3DInventorViewer*>(ecb->getUserData());
|
||||
|
||||
if (scale->points.size() == 1) {
|
||||
ecb->setHandled();
|
||||
|
||||
std::unique_ptr<SoPickedPoint> pp(view->getPointOnRay(l2e->getPosition(), scale->viewProv));
|
||||
if (pp.get()) {
|
||||
if (pp) {
|
||||
SbVec3f pos3d = pp->getPoint();
|
||||
scale->setDistance(pos3d);
|
||||
}
|
||||
@@ -606,12 +563,12 @@ void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb)
|
||||
|
||||
void InteractiveScale::soEventFilter(void* ud, SoEventCallback* ecb)
|
||||
{
|
||||
InteractiveScale* scale = static_cast<InteractiveScale*>(ud);
|
||||
auto scale = static_cast<InteractiveScale*>(ud);
|
||||
|
||||
const SoEvent* soEvent = ecb->getEvent();
|
||||
if (soEvent->isOfType(SoKeyboardEvent::getClassTypeId())) {
|
||||
/* If user presses escape, then we cancel the tool.*/
|
||||
const auto kbe = static_cast<const SoKeyboardEvent*>(soEvent);
|
||||
const auto kbe = static_cast<const SoKeyboardEvent*>(soEvent); // NOLINT
|
||||
|
||||
if (kbe->getKey() == SoKeyboardEvent::ESCAPE && kbe->getState() == SoButtonEvent::UP) {
|
||||
ecb->setHandled();
|
||||
@@ -619,7 +576,7 @@ void InteractiveScale::soEventFilter(void* ud, SoEventCallback* ecb)
|
||||
}
|
||||
}
|
||||
else if (soEvent->isOfType(SoMouseButtonEvent::getClassTypeId())) {
|
||||
const auto mbe = static_cast<const SoMouseButtonEvent*>(soEvent);
|
||||
const auto mbe = static_cast<const SoMouseButtonEvent*>(soEvent); // NOLINT
|
||||
|
||||
if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN)
|
||||
{
|
||||
@@ -637,7 +594,7 @@ void InteractiveScale::soEventFilter(void* ud, SoEventCallback* ecb)
|
||||
bool InteractiveScale::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::KeyRelease) {
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
auto keyEvent = static_cast<QKeyEvent*>(event); // NOLINT
|
||||
|
||||
/* If user press enter in the spinbox, then we validate the tool.*/
|
||||
if ((keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return)
|
||||
@@ -653,24 +610,17 @@ bool InteractiveScale::eventFilter(QObject* object, QEvent* event)
|
||||
return false;
|
||||
}
|
||||
|
||||
void InteractiveScale::setPlacement(Base::Placement plc)
|
||||
void InteractiveScale::setPlacement(const Base::Placement& plc)
|
||||
{
|
||||
placement = plc;
|
||||
double x, y, z, w;
|
||||
placement.getRotation().getValue(x, y, z, w);
|
||||
transform->rotation.setValue(x, y, z, w);
|
||||
Base::Vector3d pos = placement.getPosition();
|
||||
transform->translation.setValue(pos.x, pos.y, pos.z);
|
||||
|
||||
Base::Vector3d RN(0, 0, 1);
|
||||
RN = placement.getRotation().multVec(RN);
|
||||
measureLabel->norm.setValue(SbVec3f(RN.x, RN.y, RN.z));
|
||||
measureLabel->setPlacement(plc);
|
||||
}
|
||||
|
||||
SbVec3f InteractiveScale::getCoordsOnImagePlane(const SbVec3f& point)
|
||||
{
|
||||
// Plane form
|
||||
Base::Vector3d RX(1, 0, 0), RY(0, 1, 0);
|
||||
Base::Vector3d RX(1, 0, 0);
|
||||
Base::Vector3d RY(0, 1, 0);
|
||||
|
||||
// move to position of Sketch
|
||||
Base::Rotation tmp(placement.getRotation());
|
||||
@@ -680,10 +630,10 @@ SbVec3f InteractiveScale::getCoordsOnImagePlane(const SbVec3f& point)
|
||||
|
||||
// we use pos as the Base because in setPlacement we set transform->translation using
|
||||
// placement.getPosition() to fix the Zoffset. But this applies the X & Y translation too.
|
||||
Base::Vector3d S(point[0], point[1], point[2]);
|
||||
S.TransformToCoordinateSystem(pos, RX, RY);
|
||||
Base::Vector3d pnt(point[0], point[1], point[2]);
|
||||
pnt.TransformToCoordinateSystem(pos, RX, RY);
|
||||
|
||||
return SbVec3f(S.x, S.y, 0.);
|
||||
return {float(pnt.x), float(pnt.y), 0.0F};
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -691,7 +641,7 @@ SbVec3f InteractiveScale::getCoordsOnImagePlane(const SbVec3f& point)
|
||||
TaskImageDialog::TaskImageDialog(Image::ImagePlane* obj)
|
||||
{
|
||||
widget = new TaskImage(obj);
|
||||
Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox(
|
||||
auto taskbox = new Gui::TaskView::TaskBox(
|
||||
Gui::BitmapFactory().pixmap("image-plane"), widget->windowTitle(), true, nullptr);
|
||||
taskbox->groupLayout()->addWidget(widget);
|
||||
Content.push_back(taskbox);
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <Inventor/SbVec3f.h>
|
||||
#include <QPointer>
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
#include <Gui/QuantitySpinBox.h>
|
||||
#include <App/DocumentObserver.h>
|
||||
#include <App/ImagePlane.h>
|
||||
#include <memory>
|
||||
@@ -35,10 +34,7 @@
|
||||
|
||||
class SbVec3f;
|
||||
class SoEventCallback;
|
||||
class SoSeparator;
|
||||
class SoDatumLabel;
|
||||
class SoNodeSensor;
|
||||
class SoTransform;
|
||||
class EditableDatumLabel;
|
||||
|
||||
namespace Gui {
|
||||
|
||||
@@ -47,9 +43,10 @@ class ViewProvider;
|
||||
class InteractiveScale : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(InteractiveScale)
|
||||
|
||||
public:
|
||||
explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, Base::Placement plc);
|
||||
explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, const Base::Placement& plc);
|
||||
~InteractiveScale() override;
|
||||
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
@@ -60,15 +57,13 @@ public:
|
||||
}
|
||||
double getScaleFactor() const;
|
||||
double getDistance(const SbVec3f&) const;
|
||||
void setPlacement(Base::Placement plc);
|
||||
void setPlacement(const Base::Placement& plc);
|
||||
|
||||
private:
|
||||
static void soEventFilter(void * ud, SoEventCallback * ecb);
|
||||
static void getMousePosition(void * ud, SoEventCallback * ecb);
|
||||
void findPointOnImagePlane(SoEventCallback * ecb);
|
||||
void collectPoint(const SbVec3f&);
|
||||
void positionWidget();
|
||||
void showDistanceField();
|
||||
void setDistance(const SbVec3f&);
|
||||
|
||||
/// give the coordinates of a line on the image plane in imagePlane (2D) coordinates
|
||||
@@ -82,21 +77,18 @@ Q_SIGNALS:
|
||||
private:
|
||||
bool active;
|
||||
Base::Placement placement;
|
||||
SoSeparator* root;
|
||||
SoDatumLabel* measureLabel;
|
||||
SoTransform* transform;
|
||||
EditableDatumLabel* measureLabel;
|
||||
QPointer<Gui::View3DInventorViewer> viewer;
|
||||
ViewProvider* viewProv;
|
||||
std::vector<SbVec3f> points;
|
||||
SbVec3f midPoint;
|
||||
QuantitySpinBox* distanceBox;
|
||||
SoNodeSensor* cameraSensor;
|
||||
};
|
||||
|
||||
class Ui_TaskImage;
|
||||
class TaskImage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(TaskImage)
|
||||
|
||||
public:
|
||||
explicit TaskImage(Image::ImagePlane* obj, QWidget* parent = nullptr);
|
||||
@@ -119,6 +111,7 @@ private:
|
||||
void enableApplyBtn();
|
||||
|
||||
void restore(const Base::Placement&);
|
||||
void restoreAngles(const Base::Rotation&);
|
||||
void onPreview();
|
||||
void updateIcon();
|
||||
void updatePlacement();
|
||||
|
||||
@@ -63,6 +63,13 @@ public:
|
||||
FC_VIEW_PARAM(EnablePropertyViewForInactiveDocument,bool,Bool,true) \
|
||||
FC_VIEW_PARAM(ShowSelectionBoundingBox,bool,Bool,false) \
|
||||
FC_VIEW_PARAM(PropertyViewTimer, unsigned long, Unsigned, 100) \
|
||||
FC_VIEW_PARAM(AxisXColor,unsigned long,Unsigned,0xCC333300) \
|
||||
FC_VIEW_PARAM(AxisXAltColor,unsigned long,Unsigned,0xCC4C4C00) \
|
||||
FC_VIEW_PARAM(AxisYColor,unsigned long,Unsigned,0x33CC3300) \
|
||||
FC_VIEW_PARAM(AxisYAltColor,unsigned long,Unsigned,0x4CCC4C00) \
|
||||
FC_VIEW_PARAM(AxisZColor,unsigned long,Unsigned,0x3333CC00) \
|
||||
FC_VIEW_PARAM(AxisZAltColor,unsigned long,Unsigned,0x4C4CCC00) \
|
||||
|
||||
|
||||
#undef FC_VIEW_PARAM
|
||||
#define FC_VIEW_PARAM(_name,_ctype,_type,_def) \
|
||||
|
||||
@@ -243,7 +243,7 @@ void ViewProviderDragger::updatePlacementFromDragger(ViewProviderDragger* sudoTh
|
||||
int rCountY = draggerIn->rotationIncrementCountY.getValue();
|
||||
int rCountZ = draggerIn->rotationIncrementCountZ.getValue();
|
||||
|
||||
//just as a little sanity check make sure only 1 field has changed.
|
||||
//just as a little sanity check make sure only 1 or 2 fields has changed.
|
||||
int numberOfFieldChanged = 0;
|
||||
if (tCountX) numberOfFieldChanged++;
|
||||
if (tCountY) numberOfFieldChanged++;
|
||||
@@ -253,7 +253,7 @@ void ViewProviderDragger::updatePlacementFromDragger(ViewProviderDragger* sudoTh
|
||||
if (rCountZ) numberOfFieldChanged++;
|
||||
if (numberOfFieldChanged == 0)
|
||||
return;
|
||||
assert(numberOfFieldChanged == 1);
|
||||
assert(numberOfFieldChanged == 1 || numberOfFieldChanged == 2);
|
||||
|
||||
//helper lambdas.
|
||||
auto getVectorX = [&pMatrix]() {return Base::Vector3d(pMatrix[0], pMatrix[4], pMatrix[8]);};
|
||||
@@ -267,35 +267,35 @@ void ViewProviderDragger::updatePlacementFromDragger(ViewProviderDragger* sudoTh
|
||||
freshPlacement.move(movementVector);
|
||||
geoFeature->Placement.setValue(freshPlacement);
|
||||
}
|
||||
else if (tCountY)
|
||||
if (tCountY)
|
||||
{
|
||||
Base::Vector3d movementVector(getVectorY());
|
||||
movementVector *= (tCountY * translationIncrement);
|
||||
freshPlacement.move(movementVector);
|
||||
geoFeature->Placement.setValue(freshPlacement);
|
||||
}
|
||||
else if (tCountZ)
|
||||
if (tCountZ)
|
||||
{
|
||||
Base::Vector3d movementVector(getVectorZ());
|
||||
movementVector *= (tCountZ * translationIncrement);
|
||||
freshPlacement.move(movementVector);
|
||||
geoFeature->Placement.setValue(freshPlacement);
|
||||
}
|
||||
else if (rCountX)
|
||||
if (rCountX)
|
||||
{
|
||||
Base::Vector3d rotationVector(getVectorX());
|
||||
Base::Rotation rotation(rotationVector, rCountX * rotationIncrement);
|
||||
freshPlacement.setRotation(rotation * freshPlacement.getRotation());
|
||||
geoFeature->Placement.setValue(freshPlacement);
|
||||
}
|
||||
else if (rCountY)
|
||||
if (rCountY)
|
||||
{
|
||||
Base::Vector3d rotationVector(getVectorY());
|
||||
Base::Rotation rotation(rotationVector, rCountY * rotationIncrement);
|
||||
freshPlacement.setRotation(rotation * freshPlacement.getRotation());
|
||||
geoFeature->Placement.setValue(freshPlacement);
|
||||
}
|
||||
else if (rCountZ)
|
||||
if (rCountZ)
|
||||
{
|
||||
Base::Vector3d rotationVector(getVectorZ());
|
||||
Base::Rotation rotation(rotationVector, rCountZ * rotationIncrement);
|
||||
|
||||
@@ -837,6 +837,7 @@ DockWindowItems* StdWorkbench::setupDockWindows() const
|
||||
//root->addDockWidget("Std_HelpView", Qt::RightDockWidgetArea, true, false);
|
||||
root->addDockWidget("Std_TreeView", Qt::LeftDockWidgetArea, true, false);
|
||||
root->addDockWidget("Std_PropertyView", Qt::LeftDockWidgetArea, true, false);
|
||||
root->addDockWidget("Std_TaskView", Qt::LeftDockWidgetArea, true, true);
|
||||
root->addDockWidget("Std_SelectionView", Qt::LeftDockWidgetArea, false, false);
|
||||
root->addDockWidget("Std_ComboView", Qt::LeftDockWidgetArea, false, false);
|
||||
root->addDockWidget("Std_ReportView", Qt::BottomDockWidgetArea, true, true);
|
||||
|
||||
Reference in New Issue
Block a user