Merge branch 'master' into User/Document/Feature_level_units_selection_#7746

This commit is contained in:
AgCaliva
2023-09-18 14:01:25 -03:00
committed by GitHub
49 changed files with 2903 additions and 1496 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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.
*/

View File

@@ -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

View 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"

View 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

View File

@@ -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')

View File

@@ -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;

View File

@@ -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&);

View File

@@ -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

View File

@@ -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

View File

@@ -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 &center)
{
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) {

View File

@@ -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;

View File

@@ -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);

View File

@@ -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.

View File

@@ -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);

View File

@@ -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();

View File

@@ -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) \

View File

@@ -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);

View File

@@ -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);