Gui: allow to change orientation of image plane, implement two-side rendering
This commit is contained in:
@@ -345,6 +345,7 @@ SET(Gui_UIC_SRCS
|
||||
Placement.ui
|
||||
TextureMapping.ui
|
||||
TaskView/TaskAppearance.ui
|
||||
TaskView/TaskOrientation.ui
|
||||
TaskView/TaskSelectLinkProperty.ui
|
||||
TaskElementColors.ui
|
||||
DlgObjectSelection.ui
|
||||
@@ -726,6 +727,9 @@ SET(Task_View_SRCS
|
||||
TaskView/TaskAppearance.cpp
|
||||
TaskView/TaskAppearance.h
|
||||
TaskView/TaskAppearance.ui
|
||||
TaskView/TaskOrientation.cpp
|
||||
TaskView/TaskOrientation.h
|
||||
TaskView/TaskOrientation.ui
|
||||
TaskView/TaskSelectLinkProperty.cpp
|
||||
TaskView/TaskSelectLinkProperty.h
|
||||
TaskView/TaskSelectLinkProperty.ui
|
||||
@@ -794,6 +798,7 @@ SOURCE_GROUP("Widget\\QSintActionPanel\\Mocs" FILES ${qsint_MOC_SRCS})
|
||||
|
||||
# The 3d view
|
||||
SET(View3D_CPP_SRCS
|
||||
Camera.cpp
|
||||
Flag.cpp
|
||||
GLBuffer.cpp
|
||||
GLPainter.cpp
|
||||
@@ -824,6 +829,7 @@ SET(View3D_CPP_SRCS
|
||||
)
|
||||
SET(View3D_SRCS
|
||||
${View3D_CPP_SRCS}
|
||||
Camera.h
|
||||
Flag.h
|
||||
GLBuffer.h
|
||||
GLPainter.h
|
||||
@@ -1233,6 +1239,7 @@ if(MSVC)
|
||||
propertyeditor/PropertyItemDelegate.cpp
|
||||
propertyeditor/PropertyModel.cpp
|
||||
TaskView/TaskAppearance.cpp
|
||||
TaskView/TaskOrientation.cpp
|
||||
TaskView/TaskSelectLinkProperty.cpp
|
||||
TaskView/TaskEditControl.cpp
|
||||
TaskView/TaskView.cpp
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include "Camera.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
@@ -92,51 +93,109 @@ vz.z=0
|
||||
https://de.wikipedia.org/wiki/Arkussinus_und_Arkuskosinus
|
||||
*/
|
||||
|
||||
SbRotation Camera::top()
|
||||
{
|
||||
return SbRotation(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
SbRotation Camera::bottom()
|
||||
{
|
||||
return SbRotation(1, 0, 0, 0);
|
||||
}
|
||||
|
||||
SbRotation Camera::front()
|
||||
{
|
||||
auto root = (float)(sqrt(2.0)/2.0);
|
||||
return SbRotation(root, 0, 0, root);
|
||||
}
|
||||
|
||||
SbRotation Camera::rear()
|
||||
{
|
||||
auto root = (float)(sqrt(2.0)/2.0);
|
||||
return SbRotation(0, root, root, 0);
|
||||
}
|
||||
|
||||
SbRotation Camera::right()
|
||||
{
|
||||
return SbRotation(0.5, 0.5, 0.5, 0.5);
|
||||
}
|
||||
|
||||
SbRotation Camera::left()
|
||||
{
|
||||
return SbRotation(-0.5, 0.5, 0.5, -0.5);
|
||||
}
|
||||
|
||||
SbRotation Camera::isometric()
|
||||
{
|
||||
//from math import sqrt, degrees, asin
|
||||
//p1=App.Rotation(App.Vector(1,0,0),45)
|
||||
//p2=App.Rotation(App.Vector(0,0,1),-45)
|
||||
//p3=p2.multiply(p1)
|
||||
//return SbRotation(0.353553f, -0.146447f, -0.353553f, 0.853553f);
|
||||
|
||||
//from math import sqrt, degrees, asin
|
||||
//p1=App.Rotation(App.Vector(1,0,0),90)
|
||||
//p2=App.Rotation(App.Vector(0,0,1),135)
|
||||
//p3=App.Rotation(App.Vector(-1,1,0),degrees(asin(-sqrt(1.0/3.0))))
|
||||
//p4=p3.multiply(p2).multiply(p1)
|
||||
//return SbRotation(0.17592, 0.424708, 0.820473, 0.339851);
|
||||
|
||||
//from math import sqrt, degrees, asin
|
||||
//p1=App.Rotation(App.Vector(1,0,0),90)
|
||||
//p2=App.Rotation(App.Vector(0,0,1),45)
|
||||
//#p3=App.Rotation(App.Vector(1,1,0),45)
|
||||
//p3=App.Rotation(App.Vector(1,1,0),degrees(asin(-sqrt(1.0/3.0))))
|
||||
//p4=p3.multiply(p2).multiply(p1)
|
||||
return SbRotation(0.424708f, 0.17592f, 0.339851f, 0.820473f);
|
||||
}
|
||||
|
||||
SbRotation Camera::dimetric()
|
||||
{
|
||||
return SbRotation(0.567952f, 0.103751f, 0.146726f, 0.803205f);
|
||||
}
|
||||
|
||||
SbRotation Camera::trimetric()
|
||||
{
|
||||
return SbRotation(0.446015f, 0.119509f, 0.229575f, 0.856787f);
|
||||
}
|
||||
|
||||
SbRotation Camera::rotation(Camera::Orientation view)
|
||||
{
|
||||
switch (view) {
|
||||
case Top:
|
||||
return SbRotation(0, 0, 0, 1);
|
||||
return top();
|
||||
case Bottom:
|
||||
return SbRotation(1, 0, 0, 0);
|
||||
case Front: {
|
||||
auto root = (float)(sqrt(2.0)/2.0);
|
||||
return SbRotation(root, 0, 0, root);
|
||||
}
|
||||
case Rear: {
|
||||
auto root = (float)(sqrt(2.0)/2.0);
|
||||
return SbRotation(0, root, root, 0);
|
||||
}
|
||||
return bottom();
|
||||
case Front:
|
||||
return front();
|
||||
case Rear:
|
||||
return rear();
|
||||
case Right:
|
||||
return SbRotation(0.5, 0.5, 0.5, 0.5);
|
||||
return right();
|
||||
case Left:
|
||||
return SbRotation(-0.5, 0.5, 0.5, -0.5);
|
||||
return left();
|
||||
case Isometric:
|
||||
//from math import sqrt, degrees, asin
|
||||
//p1=App.Rotation(App.Vector(1,0,0),45)
|
||||
//p2=App.Rotation(App.Vector(0,0,1),-45)
|
||||
//p3=p2.multiply(p1)
|
||||
//return SbRotation(0.353553f, -0.146447f, -0.353553f, 0.853553f);
|
||||
|
||||
//from math import sqrt, degrees, asin
|
||||
//p1=App.Rotation(App.Vector(1,0,0),90)
|
||||
//p2=App.Rotation(App.Vector(0,0,1),135)
|
||||
//p3=App.Rotation(App.Vector(-1,1,0),degrees(asin(-sqrt(1.0/3.0))))
|
||||
//p4=p3.multiply(p2).multiply(p1)
|
||||
//return SbRotation(0.17592, 0.424708, 0.820473, 0.339851);
|
||||
|
||||
//from math import sqrt, degrees, asin
|
||||
//p1=App.Rotation(App.Vector(1,0,0),90)
|
||||
//p2=App.Rotation(App.Vector(0,0,1),45)
|
||||
//#p3=App.Rotation(App.Vector(1,1,0),45)
|
||||
//p3=App.Rotation(App.Vector(1,1,0),degrees(asin(-sqrt(1.0/3.0))))
|
||||
//p4=p3.multiply(p2).multiply(p1)
|
||||
return SbRotation(0.424708f, 0.17592f, 0.339851f, 0.820473f);
|
||||
return isometric();
|
||||
case Dimetric:
|
||||
return SbRotation(0.567952f, 0.103751f, 0.146726f, 0.803205f);
|
||||
return dimetric();
|
||||
case Trimetric:
|
||||
return SbRotation(0.446015f, 0.119509f, 0.229575f, 0.856787f);
|
||||
return trimetric();
|
||||
default:
|
||||
return SbRotation(0, 0, 0, 1);
|
||||
return top();
|
||||
}
|
||||
}
|
||||
|
||||
Base::Rotation Camera::convert(Camera::Orientation view)
|
||||
{
|
||||
return convert(Camera::rotation(view));
|
||||
}
|
||||
|
||||
Base::Rotation Camera::convert(const SbRotation& rot)
|
||||
{
|
||||
return Base::convertTo<Base::Rotation>(rot);
|
||||
}
|
||||
|
||||
SbRotation Camera::convert(const Base::Rotation& rot)
|
||||
{
|
||||
return Base::convertTo<SbRotation>(rot);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,20 @@ public:
|
||||
Trimetric,
|
||||
};
|
||||
|
||||
static SbRotation top();
|
||||
static SbRotation bottom();
|
||||
static SbRotation front();
|
||||
static SbRotation rear();
|
||||
static SbRotation right();
|
||||
static SbRotation left();
|
||||
static SbRotation isometric();
|
||||
static SbRotation dimetric();
|
||||
static SbRotation trimetric();
|
||||
|
||||
static SbRotation rotation(Orientation view);
|
||||
static Base::Rotation convert(Orientation view);
|
||||
static Base::Rotation convert(const SbRotation&);
|
||||
static SbRotation convert(const Base::Rotation&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
227
src/Gui/TaskView/TaskOrientation.cpp
Normal file
227
src/Gui/TaskView/TaskOrientation.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* 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 <QDialog>
|
||||
# include <map>
|
||||
#endif
|
||||
|
||||
#include <Base/Tools.h>
|
||||
#include <App/Document.h>
|
||||
#include <Gui/BitmapFactory.h>
|
||||
#include <Gui/Camera.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
|
||||
#include "TaskOrientation.h"
|
||||
#include "ui_TaskOrientation.h"
|
||||
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
TaskOrientation::TaskOrientation(App::GeoFeature* obj, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui_TaskOrientation)
|
||||
, feature(obj)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->Reverse_checkBox, &QCheckBox::clicked, this, &TaskOrientation::onPreview);
|
||||
connect(ui->XY_radioButton , &QRadioButton::clicked, this, &TaskOrientation::onPreview);
|
||||
connect(ui->XZ_radioButton , &QRadioButton::clicked, this, &TaskOrientation::onPreview);
|
||||
connect(ui->YZ_radioButton , &QRadioButton::clicked, this, &TaskOrientation::onPreview);
|
||||
connect(ui->Offset_doubleSpinBox, qOverload<double>(&QuantitySpinBox::valueChanged),
|
||||
this, &TaskOrientation::onPreview);
|
||||
}
|
||||
|
||||
TaskOrientation::~TaskOrientation()
|
||||
{
|
||||
}
|
||||
|
||||
void TaskOrientation::open()
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
App::Document* doc = feature->getDocument();
|
||||
doc->openTransaction(QT_TRANSLATE_NOOP("Command", "Change orientation"));
|
||||
restore(feature->Placement.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
void TaskOrientation::accept()
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
App::Document* doc = feature->getDocument();
|
||||
doc->commitTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskOrientation::reject()
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
App::Document* doc = feature->getDocument();
|
||||
doc->abortTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskOrientation::onPreview()
|
||||
{
|
||||
updateIcon();
|
||||
updatePlacement();
|
||||
}
|
||||
|
||||
void TaskOrientation::restore(const Base::Placement& plm)
|
||||
{
|
||||
auto isReversed = [](Camera::Orientation type) {
|
||||
return (type == Camera::Bottom) ||
|
||||
(type == Camera::Rear) ||
|
||||
(type == Camera::Left);
|
||||
};
|
||||
std::map<Camera::Orientation, Base::Rotation> rotations {
|
||||
{Camera::Top, Camera::convert(Camera::Top)},
|
||||
{Camera::Bottom, Camera::convert(Camera::Bottom)},
|
||||
{Camera::Front, Camera::convert(Camera::Front)},
|
||||
{Camera::Rear, Camera::convert(Camera::Rear)},
|
||||
{Camera::Right, Camera::convert(Camera::Right)},
|
||||
{Camera::Left, Camera::convert(Camera::Left)}
|
||||
};
|
||||
|
||||
Base::Rotation rot = plm.getRotation();
|
||||
Base::Vector3d pos = plm.getPosition();
|
||||
|
||||
double prec = 1.0e-5;
|
||||
for (const auto& it : rotations) {
|
||||
if (rot.isSame(it.second, prec)) {
|
||||
if (it.first == Camera::Top ||
|
||||
it.first == Camera::Bottom) {
|
||||
ui->XY_radioButton->setChecked(true);
|
||||
ui->Offset_doubleSpinBox->setValue(pos.z);
|
||||
}
|
||||
else if (it.first == Camera::Front ||
|
||||
it.first == Camera::Rear) {
|
||||
ui->XZ_radioButton->setChecked(true);
|
||||
ui->Offset_doubleSpinBox->setValue(pos.y);
|
||||
}
|
||||
else if (it.first == Camera::Right ||
|
||||
it.first == Camera::Left) {
|
||||
ui->YZ_radioButton->setChecked(true);
|
||||
ui->Offset_doubleSpinBox->setValue(pos.x);
|
||||
}
|
||||
|
||||
if (isReversed(it.first)) {
|
||||
ui->Reverse_checkBox->setChecked(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPreview();
|
||||
}
|
||||
|
||||
void TaskOrientation::updatePlacement()
|
||||
{
|
||||
Base::Placement Pos;
|
||||
double offset = ui->Offset_doubleSpinBox->value().getValue();
|
||||
bool reverse = ui->Reverse_checkBox->isChecked();
|
||||
if (ui->XY_radioButton->isChecked()) {
|
||||
if (!reverse) {
|
||||
Pos = Base::Placement(Base::Vector3d(0, 0, offset),
|
||||
Camera::convert(Camera::Top));
|
||||
}
|
||||
else {
|
||||
Pos = Base::Placement(Base::Vector3d(0, 0, offset),
|
||||
Camera::convert(Camera::Bottom));
|
||||
}
|
||||
}
|
||||
else if (ui->XZ_radioButton->isChecked()) {
|
||||
if (!reverse) {
|
||||
Pos = Base::Placement(Base::Vector3d(0, offset, 0),
|
||||
Camera::convert(Camera::Front));
|
||||
}
|
||||
else {
|
||||
Pos = Base::Placement(Base::Vector3d(0, offset, 0),
|
||||
Camera::convert(Camera::Rear));
|
||||
}
|
||||
}
|
||||
else if (ui->YZ_radioButton->isChecked()) {
|
||||
if (!reverse) {
|
||||
Pos = Base::Placement(Base::Vector3d(offset, 0, 0),
|
||||
Camera::convert(Camera::Right));
|
||||
}
|
||||
else {
|
||||
Pos = Base::Placement(Base::Vector3d(offset, 0, 0),
|
||||
Camera::convert(Camera::Left));
|
||||
}
|
||||
}
|
||||
|
||||
if (!feature.expired()) {
|
||||
feature->Placement.setValue(Pos);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskOrientation::updateIcon()
|
||||
{
|
||||
std::string icon;
|
||||
bool reverse = ui->Reverse_checkBox->isChecked();
|
||||
if (ui->XY_radioButton->isChecked()) {
|
||||
icon = reverse ? "view-bottom" : "view-top";
|
||||
}
|
||||
else if (ui->XZ_radioButton->isChecked()) {
|
||||
icon = reverse ? "view-rear" : "view-front";
|
||||
}
|
||||
else if (ui->YZ_radioButton->isChecked()) {
|
||||
icon = reverse ? "view-left" : "view-right";
|
||||
}
|
||||
|
||||
ui->previewLabel->setPixmap(
|
||||
Gui::BitmapFactory().pixmapFromSvg(icon.c_str(),
|
||||
ui->previewLabel->size()));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TaskOrientationDialog::TaskOrientationDialog(App::GeoFeature* obj)
|
||||
{
|
||||
widget = new TaskOrientation(obj);
|
||||
Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox(
|
||||
QPixmap(), widget->windowTitle(), true, nullptr);
|
||||
taskbox->groupLayout()->addWidget(widget);
|
||||
Content.push_back(taskbox);
|
||||
}
|
||||
|
||||
void TaskOrientationDialog::open()
|
||||
{
|
||||
widget->open();
|
||||
}
|
||||
|
||||
bool TaskOrientationDialog::accept()
|
||||
{
|
||||
widget->accept();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TaskOrientationDialog::reject()
|
||||
{
|
||||
widget->reject();
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "moc_TaskOrientation.cpp"
|
||||
80
src/Gui/TaskView/TaskOrientation.h
Normal file
80
src/Gui/TaskView/TaskOrientation.h
Normal file
@@ -0,0 +1,80 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* 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_TASKORIENTATION_H
|
||||
#define GUI_TASKORIENTATION_H
|
||||
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
#include <App/DocumentObserver.h>
|
||||
#include <App/GeoFeature.h>
|
||||
#include <memory>
|
||||
|
||||
namespace Gui {
|
||||
|
||||
class Ui_TaskOrientation;
|
||||
class TaskOrientation : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TaskOrientation(App::GeoFeature* obj, QWidget* parent = nullptr);
|
||||
~TaskOrientation() override;
|
||||
|
||||
void open();
|
||||
void accept();
|
||||
void reject();
|
||||
|
||||
private:
|
||||
void restore(const Base::Placement&);
|
||||
void onPreview();
|
||||
void updateIcon();
|
||||
void updatePlacement();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_TaskOrientation> ui;
|
||||
App::WeakPtrT<App::GeoFeature> feature;
|
||||
};
|
||||
|
||||
class TaskOrientationDialog : public Gui::TaskView::TaskDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TaskOrientationDialog(App::GeoFeature* obj);
|
||||
|
||||
public:
|
||||
void open() override;
|
||||
bool accept() override;
|
||||
bool reject() override;
|
||||
|
||||
QDialogButtonBox::StandardButtons getStandardButtons() const override {
|
||||
return QDialogButtonBox::Ok | QDialogButtonBox::Cancel;
|
||||
}
|
||||
|
||||
private:
|
||||
TaskOrientation* widget;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // GUI_TASKORIENTATION_H
|
||||
114
src/Gui/TaskView/TaskOrientation.ui
Normal file
114
src/Gui/TaskView/TaskOrientation.ui
Normal file
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gui::TaskOrientation</class>
|
||||
<widget class="QWidget" name="Gui::TaskOrientation">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>194</width>
|
||||
<height>200</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Choose orientation</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Planes</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="XY_radioButton">
|
||||
<property name="text">
|
||||
<string>XY-Plane</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="XZ_radioButton">
|
||||
<property name="text">
|
||||
<string>XZ-Plane</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="YZ_radioButton">
|
||||
<property name="text">
|
||||
<string>YZ-Plane</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="Reverse_checkBox">
|
||||
<property name="text">
|
||||
<string>Reverse direction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="previewLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Preview</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Offset:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="Offset_doubleSpinBox" native="true">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="minimum" stdset="0">
|
||||
<double>-999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep" stdset="0">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::QuantitySpinBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Gui/QuantitySpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -23,20 +23,25 @@
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <sstream>
|
||||
# include <QAction>
|
||||
# include <QFileInfo>
|
||||
# include <QImage>
|
||||
# include <QMenu>
|
||||
# include <QString>
|
||||
|
||||
# include <Inventor/nodes/SoCoordinate3.h>
|
||||
# include <Inventor/nodes/SoFaceSet.h>
|
||||
# include <Inventor/nodes/SoMaterial.h>
|
||||
# include <Inventor/nodes/SoSeparator.h>
|
||||
# include <Inventor/nodes/SoShapeHints.h>
|
||||
# include <Inventor/nodes/SoTexture2.h>
|
||||
# include <Inventor/nodes/SoTextureCoordinate2.h>
|
||||
#endif
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <Gui/ActionFunction.h>
|
||||
#include <Gui/BitmapFactory.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/TaskView/TaskOrientation.h>
|
||||
#include <App/ImagePlane.h>
|
||||
|
||||
#include "ViewProviderImagePlane.h"
|
||||
@@ -46,15 +51,24 @@ using namespace Gui;
|
||||
|
||||
|
||||
PROPERTY_SOURCE(Gui::ViewProviderImagePlane, Gui::ViewProviderGeometryObject)
|
||||
const char* ViewProviderImagePlane::LightingEnums[]= {"One side", "Two side", nullptr};
|
||||
|
||||
ViewProviderImagePlane::ViewProviderImagePlane()
|
||||
{
|
||||
ADD_PROPERTY_TYPE(Lighting,(1L), "Object Style", App::Prop_None, "Set object lighting.");
|
||||
Lighting.setEnums(LightingEnums);
|
||||
|
||||
texture = new SoTexture2;
|
||||
texture->ref();
|
||||
|
||||
pcCoords = new SoCoordinate3();
|
||||
pcCoords->ref();
|
||||
|
||||
shapeHints = new SoShapeHints;
|
||||
shapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE;
|
||||
shapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
|
||||
shapeHints->ref();
|
||||
|
||||
sPixmap = "image-plane";
|
||||
}
|
||||
|
||||
@@ -62,6 +76,7 @@ ViewProviderImagePlane::~ViewProviderImagePlane()
|
||||
{
|
||||
pcCoords->unref();
|
||||
texture->unref();
|
||||
shapeHints->unref();
|
||||
}
|
||||
|
||||
void ViewProviderImagePlane::attach(App::DocumentObject *pcObj)
|
||||
@@ -85,6 +100,7 @@ void ViewProviderImagePlane::attach(App::DocumentObject *pcObj)
|
||||
texture->model = SoTexture2::MODULATE;
|
||||
planesep->addChild(texture);
|
||||
|
||||
planesep->addChild(shapeHints);
|
||||
planesep->addChild(pcShapeMaterial);
|
||||
|
||||
// plane
|
||||
@@ -113,6 +129,42 @@ std::vector<std::string> ViewProviderImagePlane::getDisplayModes() const
|
||||
return StrList;
|
||||
}
|
||||
|
||||
void ViewProviderImagePlane::onChanged(const App::Property* prop)
|
||||
{
|
||||
if (prop == &Lighting) {
|
||||
if (Lighting.getValue() == 0)
|
||||
shapeHints->vertexOrdering = SoShapeHints::UNKNOWN_ORDERING;
|
||||
else
|
||||
shapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
|
||||
}
|
||||
ViewProviderGeometryObject::onChanged(prop);
|
||||
}
|
||||
|
||||
void ViewProviderImagePlane::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
|
||||
{
|
||||
ViewProviderGeometryObject::setupContextMenu(menu, receiver, member);
|
||||
|
||||
Gui::ActionFunction* func = new Gui::ActionFunction(menu);
|
||||
QAction* orient = menu->addAction(QObject::tr("Change orientation..."));
|
||||
func->trigger(orient, std::bind(&ViewProviderImagePlane::changeOrientation, this));
|
||||
|
||||
QAction* scale = menu->addAction(QObject::tr("Scale image..."));
|
||||
scale->setIcon(QIcon(QLatin1String("images:image-scaling.svg")));
|
||||
func->trigger(scale, std::bind(&ViewProviderImagePlane::scaleImage, this));
|
||||
}
|
||||
|
||||
void ViewProviderImagePlane::changeOrientation()
|
||||
{
|
||||
Gui::Control().showDialog(new TaskOrientationDialog(
|
||||
dynamic_cast<App::GeoFeature*>(getObject())
|
||||
));
|
||||
}
|
||||
|
||||
void ViewProviderImagePlane::scaleImage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool ViewProviderImagePlane::loadSvg(const char* filename, float x, float y, QImage& img)
|
||||
{
|
||||
QFileInfo fi(QString::fromUtf8(filename));
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
class SoCoordinate3;
|
||||
class SoDrawStyle;
|
||||
class SoShapeHints;
|
||||
class SoTexture2;
|
||||
class QImage;
|
||||
|
||||
@@ -39,24 +40,29 @@ class GuiExport ViewProviderImagePlane : public Gui::ViewProviderGeometryObject
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(Gui::ViewProviderImagePlane);
|
||||
|
||||
public:
|
||||
/// constructor.
|
||||
ViewProviderImagePlane();
|
||||
|
||||
/// destructor.
|
||||
~ViewProviderImagePlane() override;
|
||||
|
||||
App::PropertyEnumeration Lighting;
|
||||
|
||||
void attach(App::DocumentObject *pcObject) override;
|
||||
void setDisplayMode(const char* ModeName) override;
|
||||
std::vector<std::string> getDisplayModes() const override;
|
||||
void updateData(const App::Property*) override;
|
||||
void setupContextMenu(QMenu*, QObject*, const char*) override;
|
||||
void onChanged(const App::Property* prop) override;
|
||||
|
||||
private:
|
||||
bool loadSvg(const char*, float x, float y, QImage& img);
|
||||
void changeOrientation();
|
||||
void scaleImage();
|
||||
|
||||
protected:
|
||||
private:
|
||||
SoCoordinate3 * pcCoords;
|
||||
SoTexture2 * texture;
|
||||
};
|
||||
SoShapeHints * shapeHints;
|
||||
static const char * LightingEnums[];
|
||||
};
|
||||
|
||||
} //namespace Gui
|
||||
|
||||
|
||||
Reference in New Issue
Block a user