+ unify DLL export defines to namespace names
git-svn-id: https://free-cad.svn.sourceforge.net/svnroot/free-cad/trunk@5000 e8eeb9e2-ec13-0410-a4a9-efa5cf37419d
This commit is contained in:
494
src/Gui/Transform.cpp
Normal file
494
src/Gui/Transform.cpp
Normal file
@@ -0,0 +1,494 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2009 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#include <QDialogButtonBox>
|
||||
#include <QSignalMapper>
|
||||
|
||||
#include "Transform.h"
|
||||
#include "Selection.h"
|
||||
#include "ViewProvider.h"
|
||||
#include "ui_Placement.h"
|
||||
#include "Application.h"
|
||||
#include "Document.h"
|
||||
#include "WaitCursor.h"
|
||||
#include <App/PropertyGeo.h>
|
||||
#include <App/DocumentObject.h>
|
||||
|
||||
using namespace Gui::Dialog;
|
||||
|
||||
namespace Gui { namespace Dialog {
|
||||
class find_geometry_data
|
||||
{
|
||||
public:
|
||||
bool operator () (const std::pair<std::string, App::Property*>& elem) const
|
||||
{
|
||||
if (elem.first == "Points") {
|
||||
return elem.second->isDerivedFrom
|
||||
(Base::Type::fromName("Points::PropertyPointKernel"));
|
||||
}
|
||||
else if (elem.first == "Mesh") {
|
||||
return elem.second->isDerivedFrom
|
||||
(Base::Type::fromName("Mesh::PropertyMeshKernel"));
|
||||
}
|
||||
else if (elem.first == "Shape") {
|
||||
return elem.second->isDerivedFrom
|
||||
(Base::Type::fromName("Part::PropertyPartShape"));
|
||||
}
|
||||
|
||||
// any other geometry type
|
||||
return elem.second->isDerivedFrom
|
||||
(Base::Type::fromName("App::PropertyGeometry"));
|
||||
}
|
||||
};
|
||||
class find_placement
|
||||
{
|
||||
public:
|
||||
bool operator () (const std::pair<std::string, App::Property*>& elem) const
|
||||
{
|
||||
if (elem.first == "Placement") {
|
||||
return elem.second->isDerivedFrom
|
||||
(Base::Type::fromName("App::PropertyPlacement"));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TransformStrategy::TransformStrategy()
|
||||
{
|
||||
}
|
||||
|
||||
TransformStrategy::~TransformStrategy()
|
||||
{
|
||||
}
|
||||
|
||||
Base::Vector3d TransformStrategy::getRotationCenter() const
|
||||
{
|
||||
// get the global bounding box of all selected objects and use its center as
|
||||
// rotation center
|
||||
std::set<App::DocumentObject*> objects = transformObjects();
|
||||
if (!objects.empty()) {
|
||||
Base::BoundBox3d bbox;
|
||||
bool first=true;
|
||||
for (std::set<App::DocumentObject*>::const_iterator it=objects.begin();it!=objects.end();++it) {
|
||||
std::map<std::string,App::Property*> props;
|
||||
(*it)->getPropertyMap(props);
|
||||
// search for a data property
|
||||
std::map<std::string,App::Property*>::iterator jt;
|
||||
jt = std::find_if(props.begin(), props.end(), find_geometry_data());
|
||||
if (jt != props.end()) {
|
||||
if (first)
|
||||
bbox = (static_cast<App::PropertyGeometry*>(jt->second)->getBoundingBox());
|
||||
else
|
||||
bbox.Add(static_cast<App::PropertyGeometry*>(jt->second)->getBoundingBox());
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
return Base::Vector3d((bbox.MinX+bbox.MaxX)/2,
|
||||
(bbox.MinY+bbox.MaxY)/2,
|
||||
(bbox.MinZ+bbox.MaxZ)/2);
|
||||
}
|
||||
|
||||
return Base::Vector3d();
|
||||
}
|
||||
|
||||
void TransformStrategy::commitTransform(const Base::Matrix4D& mat)
|
||||
{
|
||||
std::set<App::DocumentObject*> objects = transformObjects();
|
||||
Gui::Document* doc = Gui::Application::Instance->activeDocument();
|
||||
if (doc) {
|
||||
doc->openCommand("Transform");
|
||||
for (std::set<App::DocumentObject*>::iterator it=objects.begin();it!=objects.end();++it) {
|
||||
acceptDataTransform(mat, *it);
|
||||
}
|
||||
doc->commitCommand();
|
||||
}
|
||||
}
|
||||
|
||||
void TransformStrategy::acceptDataTransform(const Base::Matrix4D& mat, App::DocumentObject* obj)
|
||||
{
|
||||
Gui::Document* doc = Gui::Application::Instance->getDocument(obj->getDocument());
|
||||
std::map<std::string,App::Property*> props;
|
||||
obj->getPropertyMap(props);
|
||||
// search for the placement property
|
||||
std::map<std::string,App::Property*>::iterator jt;
|
||||
jt = std::find_if(props.begin(), props.end(), find_placement());
|
||||
if (jt != props.end()) {
|
||||
Base::Placement local = static_cast<App::PropertyPlacement*>(jt->second)->getValue();
|
||||
Gui::ViewProvider* vp = doc->getViewProvider(obj);
|
||||
if (vp) vp->setTransformation(local.toMatrix());
|
||||
}
|
||||
else {
|
||||
// No placement found
|
||||
Gui::ViewProvider* vp = doc->getViewProvider(obj);
|
||||
if (vp) vp->setTransformation(Base::Matrix4D());
|
||||
}
|
||||
|
||||
// Apply the transformation
|
||||
jt = std::find_if(props.begin(), props.end(), find_geometry_data());
|
||||
if (jt != props.end()) {
|
||||
static_cast<App::PropertyGeometry*>(jt->second)->transformGeometry(mat);
|
||||
}
|
||||
}
|
||||
|
||||
void TransformStrategy::applyTransform(const Base::Placement& plm)
|
||||
{
|
||||
std::set<App::DocumentObject*> objects = transformObjects();
|
||||
for (std::set<App::DocumentObject*>::iterator it=objects.begin();it!=objects.end();++it) {
|
||||
applyViewTransform(plm, *it);
|
||||
}
|
||||
}
|
||||
|
||||
void TransformStrategy::resetTransform()
|
||||
{
|
||||
std::set<App::DocumentObject*> objects = transformObjects();
|
||||
for (std::set<App::DocumentObject*>::iterator it=objects.begin();it!=objects.end();++it) {
|
||||
resetViewTransform(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void TransformStrategy::applyViewTransform(const Base::Placement& plm, App::DocumentObject* obj)
|
||||
{
|
||||
Gui::Document* doc = Gui::Application::Instance->getDocument(obj->getDocument());
|
||||
std::map<std::string,App::Property*> props;
|
||||
obj->getPropertyMap(props);
|
||||
// search for the placement property
|
||||
std::map<std::string,App::Property*>::iterator jt;
|
||||
jt = std::find_if(props.begin(), props.end(), find_placement());
|
||||
if (jt != props.end()) {
|
||||
Base::Placement local = static_cast<App::PropertyPlacement*>(jt->second)->getValue();
|
||||
local *= plm; // in case a placement is already set
|
||||
Gui::ViewProvider* vp = doc->getViewProvider(obj);
|
||||
if (vp) vp->setTransformation(local.toMatrix());
|
||||
}
|
||||
else {
|
||||
// No placement found, so apply the transformation directly
|
||||
Gui::ViewProvider* vp = doc->getViewProvider(obj);
|
||||
if (vp) vp->setTransformation(plm.toMatrix());
|
||||
}
|
||||
}
|
||||
|
||||
void TransformStrategy::resetViewTransform(App::DocumentObject* obj)
|
||||
{
|
||||
Gui::Document* doc = Gui::Application::Instance->getDocument(obj->getDocument());
|
||||
std::map<std::string,App::Property*> props;
|
||||
obj->getPropertyMap(props);
|
||||
// search for the placement property
|
||||
std::map<std::string,App::Property*>::iterator jt;
|
||||
jt = std::find_if(props.begin(), props.end(), find_placement());
|
||||
if (jt != props.end()) {
|
||||
Base::Placement local = static_cast<App::PropertyPlacement*>(jt->second)->getValue();
|
||||
Gui::ViewProvider* vp = doc->getViewProvider(obj);
|
||||
if (vp) vp->setTransformation(local.toMatrix());
|
||||
}
|
||||
else {
|
||||
// No placement found
|
||||
Gui::ViewProvider* vp = doc->getViewProvider(obj);
|
||||
if (vp) vp->setTransformation(Base::Matrix4D());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
DefaultTransformStrategy::DefaultTransformStrategy(QWidget* w) : widget(w)
|
||||
{
|
||||
Gui::SelectionChanges mod;
|
||||
mod.Type = Gui::SelectionChanges::SetSelection;
|
||||
onSelectionChanged(mod);
|
||||
}
|
||||
|
||||
DefaultTransformStrategy::~DefaultTransformStrategy()
|
||||
{
|
||||
}
|
||||
|
||||
std::set<App::DocumentObject*> DefaultTransformStrategy::transformObjects() const
|
||||
{
|
||||
return selection;
|
||||
}
|
||||
|
||||
void DefaultTransformStrategy::onSelectionChanged(const Gui::SelectionChanges& msg)
|
||||
{
|
||||
if (msg.Type == SelectionChanges::SetPreselect ||
|
||||
msg.Type == SelectionChanges::RmvPreselect)
|
||||
return; // nothing to do
|
||||
if (msg.Type == SelectionChanges::ClrSelection) {
|
||||
widget->setDisabled(true);
|
||||
for (std::set<App::DocumentObject*>::iterator it = selection.begin();
|
||||
it != selection.end(); ++it)
|
||||
resetViewTransform(*it);
|
||||
selection.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
std::set<App::DocumentObject*> update_selection;
|
||||
std::vector<App::DocumentObject*> sel = Gui::Selection().getObjectsOfType
|
||||
(App::DocumentObject::getClassTypeId());
|
||||
for (std::vector<App::DocumentObject*>::iterator it=sel.begin();it!=sel.end();++it) {
|
||||
std::map<std::string,App::Property*> props;
|
||||
(*it)->getPropertyMap(props);
|
||||
// search for the placement property
|
||||
std::map<std::string,App::Property*>::iterator jt;
|
||||
jt = std::find_if(props.begin(), props.end(), find_geometry_data());
|
||||
if (jt != props.end()) {
|
||||
update_selection.insert(*it);
|
||||
}
|
||||
}
|
||||
|
||||
// now we remove all objects which links to another object
|
||||
// of the selected objects because if the source object changes
|
||||
// it is touched and thus a recompute later would overwrite the
|
||||
// changes here anyway
|
||||
std::set<App::DocumentObject*> filter;
|
||||
for (std::set<App::DocumentObject*>::iterator it=update_selection.begin();
|
||||
it!=update_selection.end();++it) {
|
||||
std::vector<App::DocumentObject*> deps = (*it)->getOutList();
|
||||
std::vector<App::DocumentObject*>::iterator jt;
|
||||
for (jt = deps.begin(); jt != deps.end(); ++jt) {
|
||||
if (update_selection.find(*jt) != update_selection.end()) {
|
||||
filter.insert(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!filter.empty()) {
|
||||
std::set<App::DocumentObject*> diff;
|
||||
std::insert_iterator< std::set<App::DocumentObject*> > biit(diff, diff.begin());
|
||||
std::set_difference(update_selection.begin(), update_selection.end(),
|
||||
filter.begin(), filter.end(), biit);
|
||||
update_selection = diff;
|
||||
}
|
||||
|
||||
// reset transform for all deselected objects
|
||||
std::vector<App::DocumentObject*> diff;
|
||||
std::back_insert_iterator< std::vector<App::DocumentObject*> > biit(diff);
|
||||
std::set_difference(selection.begin(), selection.end(),
|
||||
update_selection.begin(), update_selection.end(), biit);
|
||||
for (std::vector<App::DocumentObject*>::iterator it = diff.begin(); it != diff.end(); ++it)
|
||||
resetViewTransform(*it);
|
||||
selection = update_selection;
|
||||
|
||||
widget->setDisabled(selection.empty());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* TRANSLATOR Gui::Dialog::Transform */
|
||||
|
||||
Transform::Transform(QWidget* parent, Qt::WFlags fl)
|
||||
: Gui::LocationDialog(parent, fl), strategy(0)
|
||||
{
|
||||
ui = new Ui_TransformComp(this);
|
||||
ui->resetButton->hide();
|
||||
ui->applyPlacementChange->hide();
|
||||
ui->applyIncrementalPlacement->hide();
|
||||
|
||||
ui->angle->setSuffix(QString::fromUtf8(" \xc2\xb0"));
|
||||
ui->yawAngle->setSuffix(QString::fromUtf8(" \xc2\xb0"));
|
||||
ui->pitchAngle->setSuffix(QString::fromUtf8(" \xc2\xb0"));
|
||||
ui->rollAngle->setSuffix(QString::fromUtf8(" \xc2\xb0"));
|
||||
|
||||
ui->closeButton->setText(tr("Cancel"));
|
||||
this->setWindowTitle(tr("Transform"));
|
||||
|
||||
// create a signal mapper in order to have one slot to perform the change
|
||||
QSignalMapper* signalMapper = new QSignalMapper(this);
|
||||
connect(this, SIGNAL(directionChanged()), signalMapper, SLOT(map()));
|
||||
signalMapper->setMapping(this, 0);
|
||||
|
||||
int id = 1;
|
||||
QList<QDoubleSpinBox*> sb = this->findChildren<QDoubleSpinBox*>();
|
||||
for (QList<QDoubleSpinBox*>::iterator it = sb.begin(); it != sb.end(); ++it) {
|
||||
connect(*it, SIGNAL(valueChanged(double)), signalMapper, SLOT(map()));
|
||||
signalMapper->setMapping(*it, id++);
|
||||
}
|
||||
|
||||
connect(signalMapper, SIGNAL(mapped(int)),
|
||||
this, SLOT(onTransformChanged(int)));
|
||||
|
||||
setTransformStrategy(new DefaultTransformStrategy(this));
|
||||
}
|
||||
|
||||
Transform::~Transform()
|
||||
{
|
||||
delete ui;
|
||||
delete strategy;
|
||||
}
|
||||
|
||||
void Transform::setTransformStrategy(TransformStrategy* ts)
|
||||
{
|
||||
if (!ts || ts == strategy)
|
||||
return;
|
||||
if (strategy)
|
||||
delete strategy;
|
||||
strategy = ts;
|
||||
Base::Vector3d cnt = strategy->getRotationCenter();
|
||||
ui->xCnt->setValue(cnt.x);
|
||||
ui->yCnt->setValue(cnt.y);
|
||||
ui->zCnt->setValue(cnt.z);
|
||||
this->setDisabled(strategy->transformObjects().empty());
|
||||
}
|
||||
|
||||
void Transform::showStandardButtons(bool b)
|
||||
{
|
||||
ui->closeButton->setVisible(b);
|
||||
ui->oKButton->setVisible(b);
|
||||
ui->applyButton->setVisible(b);
|
||||
}
|
||||
|
||||
void Transform::onTransformChanged(int)
|
||||
{
|
||||
Base::Placement plm = this->getPlacementData();
|
||||
strategy->applyTransform(plm);
|
||||
}
|
||||
|
||||
void Transform::accept()
|
||||
{
|
||||
on_applyButton_clicked();
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void Transform::reject()
|
||||
{
|
||||
strategy->resetTransform();
|
||||
QDialog::reject();
|
||||
}
|
||||
|
||||
void Transform::on_applyButton_clicked()
|
||||
{
|
||||
Gui::WaitCursor wc;
|
||||
Base::Placement plm = this->getPlacementData();
|
||||
Base::Matrix4D mat = plm.toMatrix();
|
||||
strategy->commitTransform(mat);
|
||||
|
||||
// nullify the values
|
||||
QList<QDoubleSpinBox*> sb = this->findChildren<QDoubleSpinBox*>();
|
||||
for (QList<QDoubleSpinBox*>::iterator it = sb.begin(); it != sb.end(); ++it) {
|
||||
(*it)->blockSignals(true);
|
||||
(*it)->setValue(0.0);
|
||||
(*it)->blockSignals(false);
|
||||
}
|
||||
|
||||
Base::Vector3d cnt = strategy->getRotationCenter();
|
||||
ui->xCnt->setValue(cnt.x);
|
||||
ui->yCnt->setValue(cnt.y);
|
||||
ui->zCnt->setValue(cnt.z);
|
||||
}
|
||||
|
||||
void Transform::directionActivated(int index)
|
||||
{
|
||||
if (ui->directionActivated(this, index)) {
|
||||
/*emit*/ directionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Base::Vector3f Transform::getDirection() const
|
||||
{
|
||||
return ui->getDirection();
|
||||
}
|
||||
|
||||
Base::Placement Transform::getPlacementData() const
|
||||
{
|
||||
int index = ui->rotationInput->currentIndex();
|
||||
Base::Rotation rot;
|
||||
Base::Vector3d pos;
|
||||
Base::Vector3d cnt;
|
||||
|
||||
pos = Base::Vector3d(ui->xPos->value(),ui->yPos->value(),ui->zPos->value());
|
||||
cnt = Base::Vector3d(ui->xCnt->value(),ui->yCnt->value(),ui->zCnt->value());
|
||||
|
||||
if (index == 0) {
|
||||
Base::Vector3f dir = getDirection();
|
||||
rot.setValue(Base::Vector3d(dir.x,dir.y,dir.z),ui->angle->value()*D_PI/180.0);
|
||||
}
|
||||
else if (index == 1) {
|
||||
rot.setYawPitchRoll(
|
||||
ui->yawAngle->value(),
|
||||
ui->pitchAngle->value(),
|
||||
ui->rollAngle->value());
|
||||
}
|
||||
|
||||
Base::Placement p(pos, rot, cnt);
|
||||
return p;
|
||||
}
|
||||
|
||||
void Transform::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
ui->retranslate(this);
|
||||
ui->closeButton->setText(tr("Cancel"));
|
||||
this->setWindowTitle(tr("Transform"));
|
||||
}
|
||||
else {
|
||||
QDialog::changeEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------
|
||||
|
||||
TaskTransform::TaskTransform()
|
||||
{
|
||||
this->setButtonPosition(TaskTransform::South);
|
||||
dialog = new Transform();
|
||||
dialog->showStandardButtons(false);
|
||||
taskbox = new Gui::TaskView::TaskBox(QPixmap(), dialog->windowTitle(), true, 0);
|
||||
taskbox->groupLayout()->addWidget(dialog);
|
||||
Content.push_back(taskbox);
|
||||
}
|
||||
|
||||
TaskTransform::~TaskTransform()
|
||||
{
|
||||
// automatically deleted in the sub-class
|
||||
}
|
||||
|
||||
void TaskTransform::setTransformStrategy(TransformStrategy* ts)
|
||||
{
|
||||
dialog->setTransformStrategy(ts);
|
||||
}
|
||||
|
||||
bool TaskTransform::accept()
|
||||
{
|
||||
dialog->accept();
|
||||
return (dialog->result() == QDialog::Accepted);
|
||||
}
|
||||
|
||||
bool TaskTransform::reject()
|
||||
{
|
||||
dialog->reject();
|
||||
return (dialog->result() == QDialog::Rejected);
|
||||
}
|
||||
|
||||
void TaskTransform::clicked(int id)
|
||||
{
|
||||
if (id == QDialogButtonBox::Apply) {
|
||||
dialog->on_applyButton_clicked();
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_Transform.cpp"
|
||||
Reference in New Issue
Block a user