leocad/qt/lc_qpropertiestree.cpp

1595 lines
47 KiB
C++
Raw Normal View History

2013-08-09 06:57:18 +02:00
#include "lc_global.h"
#include "lc_qpropertiestree.h"
2023-05-16 06:12:08 +02:00
#include "lc_colorpicker.h"
2013-08-09 06:57:18 +02:00
#include "lc_application.h"
#include "lc_model.h"
#include "lc_mainwindow.h"
2013-08-09 06:57:18 +02:00
#include "object.h"
#include "piece.h"
#include "camera.h"
#include "light.h"
#include "pieceinf.h"
#include "lc_library.h"
#include "lc_qutils.h"
2020-12-18 02:59:11 +01:00
#include "lc_viewwidget.h"
#include "lc_previewwidget.h"
2013-08-09 06:57:18 +02:00
// Draw an icon indicating opened/closing branches
static QIcon drawIndicatorIcon(const QPalette &palette, QStyle *style)
{
QPixmap pix(14, 14);
pix.fill(Qt::transparent);
QStyleOption branchOption;
branchOption.rect = QRect(2, 2, 9, 9); // ### hardcoded in qcommonstyle.cpp
branchOption.palette = palette;
branchOption.state = QStyle::State_Children;
QPainter p;
// Draw closed state
p.begin(&pix);
style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p);
p.end();
QIcon rc = pix;
rc.addPixmap(pix, QIcon::Selected, QIcon::Off);
// Draw opened state
branchOption.state |= QStyle::State_Open;
pix.fill(Qt::transparent);
p.begin(&pix);
style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p);
p.end();
rc.addPixmap(pix, QIcon::Normal, QIcon::On);
rc.addPixmap(pix, QIcon::Selected, QIcon::On);
return rc;
}
static QIcon drawCheckBox(bool value)
{
QStyleOptionButton opt;
opt.state |= value ? QStyle::State_On : QStyle::State_Off;
opt.state |= QStyle::State_Enabled;
const QStyle *style = QApplication::style();
// Figure out size of an indicator and make sure it is not scaled down in a list view item
// by making the pixmap as big as a list view icon and centering the indicator in it.
// (if it is smaller, it can't be helped)
const int indicatorWidth = style->pixelMetric(QStyle::PM_IndicatorWidth, &opt);
const int indicatorHeight = style->pixelMetric(QStyle::PM_IndicatorHeight, &opt);
const int listViewIconSize = indicatorWidth;
const int pixmapWidth = indicatorWidth;
const int pixmapHeight = qMax(indicatorHeight, listViewIconSize);
opt.rect = QRect(0, 0, indicatorWidth, indicatorHeight);
QPixmap pixmap = QPixmap(pixmapWidth, pixmapHeight);
pixmap.fill(Qt::transparent);
{
// Center?
const int xoff = (pixmapWidth > indicatorWidth) ? (pixmapWidth - indicatorWidth) / 2 : 0;
const int yoff = (pixmapHeight > indicatorHeight) ? (pixmapHeight - indicatorHeight) / 2 : 0;
QPainter painter(&pixmap);
painter.translate(xoff, yoff);
style->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, &painter);
}
return QIcon(pixmap);
}
int lcQPropertiesTreeDelegate::indentation(const QModelIndex &index) const
{
if (!m_treeWidget)
return 0;
QTreeWidgetItem *item = m_treeWidget->indexToItem(index);
int indent = 0;
while (item->parent())
{
item = item->parent();
++indent;
}
if (m_treeWidget->rootIsDecorated())
++indent;
return indent * m_treeWidget->indentation();
}
void lcQPropertiesTreeDelegate::slotEditorDestroyed(QObject *object)
{
if (m_editedWidget == object)
{
m_editedWidget = nullptr;
m_editedItem = nullptr;
2013-08-09 06:57:18 +02:00
}
}
QWidget *lcQPropertiesTreeDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &style, const QModelIndex &index) const
{
2016-02-17 00:11:52 +01:00
Q_UNUSED(style);
2013-08-09 06:57:18 +02:00
if (index.column() == 1 && m_treeWidget)
{
QTreeWidgetItem *item = m_treeWidget->indexToItem(index);
if (item && (item->flags() & Qt::ItemIsEnabled))
{
QWidget *editor = m_treeWidget->createEditor(parent, item);
if (editor)
{
editor->setAutoFillBackground(true);
editor->installEventFilter(const_cast<lcQPropertiesTreeDelegate *>(this));
m_editedItem = item;
m_editedWidget = editor;
connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *)));
return editor;
}
}
}
return nullptr;
2013-08-09 06:57:18 +02:00
}
void lcQPropertiesTreeDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index)
editor->setGeometry(option.rect.adjusted(0, 0, 0, -1));
}
void lcQPropertiesTreeDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
bool hasValue = true;
if (m_treeWidget)
hasValue = m_treeWidget->indexToItem(index)->data(0, lcQPropertiesTree::PropertyTypeRole).toInt() != lcQPropertiesTree::PropertyGroup;
QStyleOptionViewItem opt = option;
2013-08-09 06:57:18 +02:00
opt.state &= ~QStyle::State_HasFocus;
2017-02-13 03:05:20 +01:00
if (index.column() == 1 && m_treeWidget)
2013-08-09 06:57:18 +02:00
{
QTreeWidgetItem *item = m_treeWidget->indexToItem(index);
if (m_editedItem && m_editedItem == item)
m_disablePainting = true;
}
QItemDelegate::paint(painter, opt, index);
if (option.type)
m_disablePainting = false;
opt.palette.setCurrentColorGroup(QPalette::Active);
QColor color = static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt));
painter->save();
painter->setPen(QPen(color));
2023-08-04 22:26:29 +02:00
2013-08-09 06:57:18 +02:00
if (!m_treeWidget || (!m_treeWidget->lastColumn(index.column()) && hasValue))
{
int right = (option.direction == Qt::LeftToRight) ? option.rect.right() : option.rect.left();
painter->drawLine(right, option.rect.y(), right, option.rect.bottom());
}
painter->restore();
}
void lcQPropertiesTreeDelegate::drawDecoration(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QPixmap &pixmap) const
{
if (m_disablePainting)
return;
QItemDelegate::drawDecoration(painter, option, rect, pixmap);
}
void lcQPropertiesTreeDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const
{
if (m_disablePainting)
return;
QItemDelegate::drawDisplay(painter, option, rect, text);
}
QSize lcQPropertiesTreeDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return QItemDelegate::sizeHint(option, index) + QSize(3, 4);
}
bool lcQPropertiesTreeDelegate::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::FocusOut)
{
QFocusEvent *fe = static_cast<QFocusEvent *>(event);
if (fe->reason() == Qt::ActiveWindowFocusReason)
return false;
}
return QItemDelegate::eventFilter(object, event);
}
lcQPropertiesTree::lcQPropertiesTree(QWidget *parent) :
QTreeWidget(parent)
{
setIconSize(QSize(18, 18));
setColumnCount(2);
QStringList labels;
labels.append(tr("Property"));
labels.append(tr("Value"));
setHeaderLabels(labels);
2014-01-26 07:56:36 +01:00
header()->setSectionsMovable(false);
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
2013-08-09 06:57:18 +02:00
header()->setVisible(false);
setAlternatingRowColors(true);
setRootIsDecorated(false);
setEditTriggers(QAbstractItemView::EditKeyPressed);
m_expandIcon = drawIndicatorIcon(palette(), style());
m_checkedIcon = drawCheckBox(true);
m_uncheckedIcon = drawCheckBox(false);
2023-08-27 20:17:07 +02:00
mDelegate = new lcQPropertiesTreeDelegate(parent);
mDelegate->setTreeWidget(this);
setItemDelegate(mDelegate);
2013-08-09 06:57:18 +02:00
SetEmpty();
2013-08-09 06:57:18 +02:00
connect(header(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(resizeColumnToContents(int)));
}
QSize lcQPropertiesTree::sizeHint() const
{
return QSize(200, -1);
}
void lcQPropertiesTree::drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem opt = option;
2013-08-09 06:57:18 +02:00
QTreeWidgetItem *item = itemFromIndex(index);
if (item->data(0, lcQPropertiesTree::PropertyTypeRole).toInt() == lcQPropertiesTree::PropertyGroup)
{
const QColor c = option.palette.color(QPalette::Dark);
painter->fillRect(option.rect, c);
opt.palette.setColor(QPalette::AlternateBase, c);
}
QTreeWidget::drawRow(painter, opt, index);
QColor color = static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt));
painter->save();
painter->setPen(QPen(color));
painter->drawLine(opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
painter->restore();
}
void lcQPropertiesTree::keyPressEvent(QKeyEvent *event)
{
switch (event->key())
{
case Qt::Key_Return:
case Qt::Key_Enter:
case Qt::Key_Space: // Trigger Edit
2023-08-27 20:17:07 +02:00
if (!mDelegate->editedItem())
2013-08-09 06:57:18 +02:00
{
if (const QTreeWidgetItem *item = currentItem())
{
if (item->columnCount() >= 2 && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled)))
{
event->accept();
// If the current position is at column 0, move to 1.
QModelIndex index = currentIndex();
if (index.column() == 0)
{
index = index.sibling(index.row(), 1);
setCurrentIndex(index);
}
edit(index);
return;
}
}
}
break;
default:
break;
}
QTreeWidget::keyPressEvent(event);
}
void lcQPropertiesTree::mousePressEvent(QMouseEvent *event)
{
QTreeWidget::mousePressEvent(event);
QTreeWidgetItem *item = itemAt(event->pos());
if (item)
{
2023-08-27 20:17:07 +02:00
if ((item != mDelegate->editedItem()) && (event->button() == Qt::LeftButton) && (header()->logicalIndexAt(event->pos().x()) == 1) &&
2023-08-13 15:15:52 +02:00
((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled)))
2013-08-09 06:57:18 +02:00
editItem(item, 1);
}
}
void lcQPropertiesTree::Update(const lcArray<lcObject*>& Selection, lcObject* Focus)
2013-08-09 06:57:18 +02:00
{
lcPropertyWidgetMode Mode = LC_PROPERTY_WIDGET_EMPTY;
if (Focus)
2013-08-09 06:57:18 +02:00
{
switch (Focus->GetType())
{
2020-04-19 04:45:21 +02:00
case lcObjectType::Piece:
Mode = LC_PROPERTY_WIDGET_PIECE;
break;
2020-04-19 04:45:21 +02:00
case lcObjectType::Camera:
Mode = LC_PROPERTY_WIDGET_CAMERA;
break;
2020-04-19 04:45:21 +02:00
case lcObjectType::Light:
Mode = LC_PROPERTY_WIDGET_LIGHT;
break;
}
2013-08-09 06:57:18 +02:00
}
else
{
for (int ObjectIdx = 0; ObjectIdx < Selection.GetSize(); ObjectIdx++)
{
switch (Selection[ObjectIdx]->GetType())
{
2020-04-19 04:45:21 +02:00
case lcObjectType::Piece:
if (Mode == LC_PROPERTY_WIDGET_EMPTY)
Mode = LC_PROPERTY_WIDGET_PIECE;
else if (Mode != LC_PROPERTY_WIDGET_PIECE)
{
Mode = LC_PROPERTY_WIDGET_MULTIPLE;
ObjectIdx = Selection.GetSize();
}
break;
2013-08-09 06:57:18 +02:00
2020-04-19 04:45:21 +02:00
case lcObjectType::Camera:
if (Mode != LC_PROPERTY_WIDGET_EMPTY)
{
Mode = LC_PROPERTY_WIDGET_MULTIPLE;
ObjectIdx = Selection.GetSize();
}
else
{
Mode = LC_PROPERTY_WIDGET_CAMERA;
Focus = Selection[ObjectIdx];
}
break;
2020-04-19 04:45:21 +02:00
case lcObjectType::Light:
if (Mode != LC_PROPERTY_WIDGET_EMPTY)
{
Mode = LC_PROPERTY_WIDGET_MULTIPLE;
ObjectIdx = Selection.GetSize();
}
else
{
Mode = LC_PROPERTY_WIDGET_LIGHT;
Focus = Selection[ObjectIdx];
}
break;
}
}
}
switch (Mode)
2013-08-09 06:57:18 +02:00
{
case LC_PROPERTY_WIDGET_EMPTY:
SetEmpty();
break;
case LC_PROPERTY_WIDGET_PIECE:
SetPiece(Selection, Focus);
2013-08-09 06:57:18 +02:00
break;
case LC_PROPERTY_WIDGET_CAMERA:
SetCamera(Focus);
2013-08-09 06:57:18 +02:00
break;
case LC_PROPERTY_WIDGET_LIGHT:
SetLight(Focus);
break;
case LC_PROPERTY_WIDGET_MULTIPLE:
SetMultiple();
2013-08-09 06:57:18 +02:00
break;
}
}
class lcStepValidator : public QIntValidator
{
public:
lcStepValidator(lcStep Min, lcStep Max, bool AllowEmpty)
2020-01-27 21:01:52 +01:00
: QIntValidator(1, INT_MAX), mMin(Min), mMax(Max), mAllowEmpty(AllowEmpty)
{
}
QValidator::State validate(QString& Input, int& Pos) const override
{
if (mAllowEmpty && Input.isEmpty())
return Acceptable;
bool Ok;
lcStep Step = Input.toUInt(&Ok);
if (Ok)
return (Step >= mMin && Step <= mMax) ? Acceptable : Invalid;
return QIntValidator::validate(Input, Pos);
}
protected:
lcStep mMin;
lcStep mMax;
bool mAllowEmpty;
};
2023-09-10 03:25:34 +02:00
QWidget* lcQPropertiesTree::createEditor(QWidget* Parent, QTreeWidgetItem* Item) const
2013-08-09 06:57:18 +02:00
{
2023-09-10 03:25:34 +02:00
lcQPropertiesTree::PropertyType PropertyType = (lcQPropertiesTree::PropertyType)Item->data(0, lcQPropertiesTree::PropertyTypeRole).toInt();
2013-08-09 06:57:18 +02:00
2023-09-10 03:25:34 +02:00
switch (PropertyType)
2013-08-09 06:57:18 +02:00
{
case PropertyGroup:
2014-05-03 03:22:24 +02:00
case PropertyBool:
2023-09-02 19:21:25 +02:00
return nullptr;
2014-05-03 03:22:24 +02:00
2013-08-09 06:57:18 +02:00
case PropertyFloat:
{
2023-09-10 03:25:34 +02:00
QLineEdit* Editor = new QLineEdit(Parent);
float Value = Item->data(0, PropertyValueRole).toFloat();
QPointF Range = Item->data(0, PropertyRangeRole).toPointF();
2013-08-09 06:57:18 +02:00
2023-09-10 03:25:34 +02:00
Editor->setValidator(Range.isNull() ? new QDoubleValidator(Editor) : new QDoubleValidator(Range.x(), Range.y(), 1, Editor));
Editor->setText(lcFormatValueLocalized(Value));
2013-08-09 06:57:18 +02:00
2023-09-10 03:25:34 +02:00
connect(Editor, &QLineEdit::returnPressed, this, &lcQPropertiesTree::slotReturnPressed);
2013-08-09 06:57:18 +02:00
2023-09-10 03:25:34 +02:00
return Editor;
2023-08-04 22:26:29 +02:00
}
2023-11-20 03:05:43 +01:00
case PropertyInteger:
{
QLineEdit* Editor = new QLineEdit(Parent);
int Value = Item->data(0, PropertyValueRole).toInt();
QPoint Range = Item->data(0, PropertyRangeRole).toPoint();
Editor->setValidator(Range.isNull() ? new QIntValidator(Editor) : new QIntValidator(Range.x(), Range.y(), Editor));
Editor->setText(QString::number(Value));
connect(Editor, &QLineEdit::returnPressed, this, &lcQPropertiesTree::slotReturnPressed);
return Editor;
}
case PropertyStep:
2013-08-09 06:57:18 +02:00
{
2023-09-10 03:25:34 +02:00
QLineEdit* Editor = new QLineEdit(Parent);
2013-08-09 06:57:18 +02:00
2023-09-10 03:25:34 +02:00
lcStep Value = Item->data(0, PropertyValueRole).toUInt();
lcStep Show = partShow->data(0, PropertyValueRole).toUInt();
lcStep Hide = partHide->data(0, PropertyValueRole).toUInt();
2013-08-09 06:57:18 +02:00
if (Show && Hide)
{
2023-09-10 03:25:34 +02:00
if (Item == partShow)
Editor->setValidator(new lcStepValidator(1, Hide - 1, false));
else
Editor->setValidator(new lcStepValidator(Show + 1, LC_STEP_MAX, true));
}
else
2023-09-10 03:25:34 +02:00
Editor->setValidator(new lcStepValidator(1, LC_STEP_MAX, Item == partHide));
2013-08-09 06:57:18 +02:00
2023-09-10 03:25:34 +02:00
if (Item != partHide || Value != LC_STEP_MAX)
Editor->setText(QString::number(Value));
connect(Editor, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
return Editor;
2013-08-09 06:57:18 +02:00
}
case PropertyString:
{
2023-09-10 03:25:34 +02:00
QLineEdit *editor = new QLineEdit(Parent);
QString value = Item->data(0, PropertyValueRole).toString();
2013-08-09 06:57:18 +02:00
editor->setText(value);
connect(editor, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
return editor;
}
2023-09-02 05:46:29 +02:00
case PropertyStringList:
{
2023-09-10 03:25:34 +02:00
QComboBox* editor = new QComboBox(Parent);
2023-09-02 05:46:29 +02:00
2023-09-10 03:25:34 +02:00
if (Item == mCameraProjectionItem)
2023-09-02 19:21:25 +02:00
{
editor->addItems( { tr("Perspective"), tr("Orthographic") } );
}
2023-09-10 03:25:34 +02:00
else if (Item == mLightTypeItem)
2023-09-02 19:21:25 +02:00
{
2023-09-02 05:46:29 +02:00
for (int LightTypeIndex = 0; LightTypeIndex < static_cast<int>(lcLightType::Count); LightTypeIndex++)
editor->addItem(lcLight::GetLightTypeString(static_cast<lcLightType>(LightTypeIndex)));
}
else if (Item == mLightAreaShapeItem)
{
for (int LightAreaShapeIndex = 0; LightAreaShapeIndex < static_cast<int>(lcLightAreaShape::Count); LightAreaShapeIndex++)
editor->addItem(lcLight::GetAreaShapeString(static_cast<lcLightAreaShape>(LightAreaShapeIndex)));
2023-09-02 19:21:25 +02:00
}
2023-09-02 05:46:29 +02:00
2023-09-10 03:25:34 +02:00
int value = Item->data(0, PropertyValueRole).toInt();
2023-09-02 05:46:29 +02:00
editor->setCurrentIndex(value);
connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int)));
return editor;
}
2023-08-04 22:26:29 +02:00
2023-09-02 19:21:25 +02:00
case PropertyColor:
2023-08-04 22:26:29 +02:00
{
2023-09-10 03:25:34 +02:00
QPushButton *Editor = new QPushButton(Parent);
QColor Value = Item->data(0, PropertyValueRole).value<QColor>();
2023-08-04 22:26:29 +02:00
2023-08-27 20:17:07 +02:00
UpdateLightColorEditor(Editor, Value);
2023-08-04 22:26:29 +02:00
2023-08-27 20:17:07 +02:00
connect(Editor, &QPushButton::clicked, this, &lcQPropertiesTree::LightColorButtonClicked);
2023-08-04 22:26:29 +02:00
2023-08-27 20:17:07 +02:00
return Editor;
2023-08-04 22:26:29 +02:00
}
2023-09-02 19:21:25 +02:00
case PropertyPieceColor:
2013-08-09 06:57:18 +02:00
{
2023-09-10 03:25:34 +02:00
QPushButton *editor = new QPushButton(Parent);
int value = Item->data(0, PropertyValueRole).toInt();
2013-08-09 06:57:18 +02:00
updateColorEditor(editor, value);
connect(editor, SIGNAL(clicked()), this, SLOT(slotColorButtonClicked()));
return editor;
}
case PropertyPart:
{
2023-09-10 03:25:34 +02:00
QComboBox *editor = new QComboBox(Parent);
2013-08-09 06:57:18 +02:00
editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
editor->setMinimumContentsLength(1);
2017-07-24 04:35:18 +02:00
lcPiecesLibrary* Library = lcGetPiecesLibrary();
std::vector<PieceInfo*> SortedPieces;
SortedPieces.reserve(Library->mPieces.size());
const lcModel* ActiveModel = gMainWindow->GetActiveModel();
2018-02-22 02:27:24 +01:00
for (const auto& PartIt : Library->mPieces)
{
PieceInfo* Info = PartIt.second;
if (!Info->IsModel() || !Info->GetModel()->IncludesModel(ActiveModel))
SortedPieces.push_back(PartIt.second);
}
auto PieceCompare = [](PieceInfo* Info1, PieceInfo* Info2)
{
return strcmp(Info1->m_strDescription, Info2->m_strDescription) < 0;
};
2017-09-02 02:09:27 +02:00
std::sort(SortedPieces.begin(), SortedPieces.end(), PieceCompare);
for (PieceInfo* Info : SortedPieces)
2020-02-24 23:31:08 +01:00
editor->addItem(Info->m_strDescription, QVariant::fromValue((void*)Info));
2013-08-09 06:57:18 +02:00
2023-09-10 03:25:34 +02:00
PieceInfo *info = (PieceInfo*)Item->data(0, PropertyValueRole).value<void*>();
2020-02-24 23:31:08 +01:00
editor->setCurrentIndex(editor->findData(QVariant::fromValue((void*)info)));
2013-08-09 06:57:18 +02:00
connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int)));
return editor;
}
}
return nullptr;
2013-08-09 06:57:18 +02:00
}
void lcQPropertiesTree::updateColorEditor(QPushButton *editor, int value) const
{
QImage img(12, 12, QImage::Format_ARGB32);
img.fill(0);
lcColor* color = &gColorList[value];
QPainter painter(&img);
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.setPen(Qt::darkGray);
painter.setBrush(QColor::fromRgbF(color->Value[0], color->Value[1], color->Value[2]));
painter.drawRect(0, 0, img.width() - 1, img.height() - 1);
2013-08-09 06:57:18 +02:00
painter.end();
editor->setStyleSheet("Text-align:left");
editor->setIcon(QPixmap::fromImage(img));
editor->setText(color->Name);
}
2023-08-27 20:17:07 +02:00
void lcQPropertiesTree::UpdateLightColorEditor(QPushButton* Editor, QColor Color) const
2023-08-04 22:26:29 +02:00
{
2023-08-27 20:17:07 +02:00
QImage Image(12, 12, QImage::Format_ARGB32);
Image.fill(0);
QPainter Painter(&Image);
Painter.setCompositionMode(QPainter::CompositionMode_Source);
Painter.setPen(Qt::darkGray);
Painter.setBrush(Color);
Painter.drawRect(0, 0, Image.width() - 1, Image.height() - 1);
Painter.end();
Editor->setStyleSheet("Text-align:left");
Editor->setIcon(QPixmap::fromImage(Image));
Editor->setText(Color.name().toUpper());
2023-08-04 22:26:29 +02:00
}
void lcQPropertiesTree::slotToggled(bool Value)
2014-05-03 03:22:24 +02:00
{
2023-08-27 20:17:07 +02:00
QTreeWidgetItem* Item = mDelegate->editedItem();
lcModel* Model = gMainWindow->GetActiveModel();
2023-08-04 22:26:29 +02:00
lcObject* Focus = Model->GetFocusObject();
2014-05-03 03:22:24 +02:00
2023-09-02 19:21:25 +02:00
if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT)
2023-08-04 22:26:29 +02:00
{
lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr;
if (Light)
{
if (Item == mLightCastShadowItem)
2023-08-04 22:26:29 +02:00
{
2023-09-02 19:40:52 +02:00
Model->SetLightCastShadow(Light, Value);
2023-08-04 22:26:29 +02:00
}
}
}
2014-05-03 03:22:24 +02:00
}
2013-08-09 06:57:18 +02:00
void lcQPropertiesTree::slotReturnPressed()
{
QLineEdit* Editor = (QLineEdit*)sender();
2023-08-27 20:17:07 +02:00
QTreeWidgetItem* Item = mDelegate->editedItem();
lcModel* Model = gMainWindow->GetActiveModel();
2013-08-09 06:57:18 +02:00
2023-10-01 21:49:35 +02:00
lcPiece* Piece = (mFocus && mFocus->IsPiece()) ? (lcPiece*)mFocus : nullptr;
lcLight* Light = (mFocus && mFocus->IsLight()) ? (lcLight*)mFocus : nullptr;
if (Item == mPositionXItem || Item == mPositionYItem || Item == mPositionZItem)
2013-08-09 06:57:18 +02:00
{
2023-10-01 21:49:35 +02:00
lcVector3 Center;
lcMatrix33 RelativeRotation;
Model->GetMoveRotateTransform(Center, RelativeRotation);
lcVector3 Position = Center;
float Value = lcParseValueLocalized(Editor->text());
if (Item == mPositionXItem)
Position[0] = Value;
else if (Item == mPositionYItem)
Position[1] = Value;
else if (Item == mPositionZItem)
Position[2] = Value;
lcVector3 Distance = Position - Center;
Model->MoveSelectedObjects(Distance, Distance, false, true, true, true);
}
else if (Item == mRotationXItem || Item == mRotationYItem || Item == mRotationZItem)
{
lcVector3 InitialRotation(0.0f, 0.0f, 0.0f);
2013-08-09 06:57:18 +02:00
2023-10-01 21:49:35 +02:00
if (Piece)
InitialRotation = lcMatrix44ToEulerAngles(Piece->mModelWorld) * LC_RTOD;
else if (Light)
InitialRotation = lcMatrix44ToEulerAngles(Light->mWorldMatrix) * LC_RTOD;
2023-10-01 21:49:35 +02:00
lcVector3 Rotation = InitialRotation;
2023-10-01 21:49:35 +02:00
float Value = lcParseValueLocalized(Editor->text());
2023-10-01 21:49:35 +02:00
if (Item == mRotationXItem)
Rotation[0] = Value;
else if (Item == mRotationYItem)
Rotation[1] = Value;
else if (Item == mRotationZItem)
Rotation[2] = Value;
Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, true, true);
}
if (mWidgetMode == LC_PROPERTY_WIDGET_PIECE)
{
if (Item == partShow)
2013-08-09 06:57:18 +02:00
{
bool Ok = false;
lcStep Step = Editor->text().toUInt(&Ok);
2013-08-09 06:57:18 +02:00
if (Ok)
Model->SetSelectedPiecesStepShow(Step);
2013-08-09 06:57:18 +02:00
}
else if (Item == partHide)
2013-08-09 06:57:18 +02:00
{
QString Text = Editor->text();
if (Text.isEmpty())
Model->SetSelectedPiecesStepHide(LC_STEP_MAX);
else
{
bool Ok = false;
lcStep Step = Text.toUInt(&Ok);
2013-08-09 06:57:18 +02:00
if (Ok)
Model->SetSelectedPiecesStepHide(Step);
}
2013-08-09 06:57:18 +02:00
}
}
else if (mWidgetMode == LC_PROPERTY_WIDGET_CAMERA)
2013-08-09 06:57:18 +02:00
{
lcCamera* Camera = (mFocus && mFocus->IsCamera()) ? (lcCamera*)mFocus : nullptr;
2013-08-09 06:57:18 +02:00
if (Camera)
2013-08-09 06:57:18 +02:00
{
if (Item == cameraPositionX || Item == cameraPositionY || Item == cameraPositionZ)
{
lcVector3 Center = Camera->mPosition;
lcVector3 Position = Center;
float Value = lcParseValueLocalized(Editor->text());
2013-08-09 06:57:18 +02:00
if (Item == cameraPositionX)
Position[0] = Value;
else if (Item == cameraPositionY)
Position[1] = Value;
else if (Item == cameraPositionZ)
Position[2] = Value;
2013-08-09 06:57:18 +02:00
lcVector3 Distance = Position - Center;
2013-08-09 06:57:18 +02:00
Model->MoveSelectedObjects(Distance, Distance, false, false, true, true);
}
else if (Item == cameraTargetX || Item == cameraTargetY || Item == cameraTargetZ)
{
lcVector3 Center = Camera->mTargetPosition;
lcVector3 Position = Center;
float Value = lcParseValueLocalized(Editor->text());
2013-08-09 06:57:18 +02:00
if (Item == cameraTargetX)
Position[0] = Value;
else if (Item == cameraTargetY)
Position[1] = Value;
else if (Item == cameraTargetZ)
Position[2] = Value;
2013-08-09 06:57:18 +02:00
lcVector3 Distance = Position - Center;
2013-08-09 06:57:18 +02:00
Model->MoveSelectedObjects(Distance, Distance, false, false, true, true);
}
else if (Item == cameraUpX || Item == cameraUpY || Item == cameraUpZ)
{
lcVector3 Center = Camera->mUpVector;
lcVector3 Position = Center;
float Value = lcParseValueLocalized(Editor->text());
2013-08-09 06:57:18 +02:00
if (Item == cameraUpX)
Position[0] = Value;
else if (Item == cameraUpY)
Position[1] = Value;
else if (Item == cameraUpZ)
Position[2] = Value;
2013-08-09 06:57:18 +02:00
lcVector3 Distance = Position - Center;
2013-08-09 06:57:18 +02:00
Model->MoveSelectedObjects(Distance, Distance, false, false, true, true);
}
else if (Item == cameraFOV)
{
float Value = lcParseValueLocalized(Editor->text());
2013-08-09 06:57:18 +02:00
Model->SetCameraFOV(Camera, Value);
}
else if (Item == cameraNear)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetCameraZNear(Camera, Value);
}
else if (Item == cameraFar)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetCameraZFar(Camera, Value);
}
2023-09-02 19:21:25 +02:00
else if (Item == mCameraNameItem)
{
QString Value = Editor->text();
2020-12-14 01:27:21 +01:00
Model->SetCameraName(Camera, Value);
}
2013-08-09 06:57:18 +02:00
}
}
2023-08-04 22:26:29 +02:00
else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT)
{
if (Light)
{
2023-12-17 20:37:11 +01:00
if (Item == mLightAttenuationDistanceItem)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetLightAttenuationDistance(Light, Value);
}
else if (Item == mLightAttenuationPowerItem)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetLightAttenuationPower(Light, Value);
}
else if (Item == mLightSpotConeAngleItem)
2023-09-10 03:25:34 +02:00
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetSpotLightConeAngle(Light, Value);
}
else if (Item == mLightSpotPenumbraAngleItem)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetSpotLightPenumbraAngle(Light, Value);
}
else if (Item == mLightSpotTightnessItem)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetSpotLightTightness(Light, Value);
}
2023-11-20 03:05:43 +01:00
else if (Item == mLightAreaGridXItem)
{
lcVector2i AreaGrid = Light->GetAreaGrid();
AreaGrid.x = Editor->text().toInt();
Model->SetLightAreaGrid(Light, AreaGrid);
}
else if (Item == mLightAreaGridYItem)
{
lcVector2i AreaGrid = Light->GetAreaGrid();
AreaGrid.y = Editor->text().toInt();
Model->SetLightAreaGrid(Light, AreaGrid);
}
else if (Item == mLightSizeXItem)
{
lcVector2 Value = Light->GetSize();
Value[0] = lcParseValueLocalized(Editor->text());
Model->SetLightSize(Light, Value);
}
else if (Item == mLightSizeYItem)
{
lcVector2 Value = Light->GetSize();
Value[1] = lcParseValueLocalized(Editor->text());
Model->SetLightSize(Light, Value);
2023-08-04 22:26:29 +02:00
}
2023-10-01 22:16:26 +02:00
else if (Item == mLightPowerItem)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetLightPower(Light, Value);
}
2023-09-02 19:21:25 +02:00
else if (Item == mLightNameItem)
2023-08-04 22:26:29 +02:00
{
QString Value = Editor->text();
2023-08-26 21:41:16 +02:00
Model->SetLightName(Light, Value);
2023-08-04 22:26:29 +02:00
}
}
}
2013-08-09 06:57:18 +02:00
}
void lcQPropertiesTree::slotSetValue(int Value)
2013-08-09 06:57:18 +02:00
{
2023-08-27 20:17:07 +02:00
QTreeWidgetItem* Item = mDelegate->editedItem();
lcModel* Model = gMainWindow->GetActiveModel();
2013-08-09 06:57:18 +02:00
if (mWidgetMode == LC_PROPERTY_WIDGET_PIECE)
2013-08-09 06:57:18 +02:00
{
2023-09-02 19:21:25 +02:00
if (Item == mPieceColorItem)
2013-08-09 06:57:18 +02:00
{
Model->SetSelectedPiecesColorIndex(Value);
2013-08-09 06:57:18 +02:00
2023-08-27 20:17:07 +02:00
QPushButton *editor = (QPushButton*)mDelegate->editor();
updateColorEditor(editor, Value);
2013-08-09 06:57:18 +02:00
}
2023-09-02 19:21:25 +02:00
else if (Item == mPieceIdItem)
2013-08-09 06:57:18 +02:00
{
QComboBox *editor = (QComboBox*)sender();
PieceInfo* Info = (PieceInfo*)editor->itemData(Value).value<void*>();
Model->SetSelectedPiecesPieceInfo(Info);
int ColorIndex = gDefaultColor;
lcObject* Focus = gMainWindow->GetActiveModel()->GetFocusObject();
if (Focus && Focus->IsPiece())
2021-01-17 03:27:39 +01:00
ColorIndex = ((lcPiece*)Focus)->GetColorIndex();
quint32 ColorCode = lcGetColorCode(ColorIndex);
gMainWindow->PreviewPiece(Info->mFileName, ColorCode, false);
2013-08-09 06:57:18 +02:00
}
}
2023-09-02 19:21:25 +02:00
else if (mWidgetMode == LC_PROPERTY_WIDGET_CAMERA)
{
lcObject* Focus = Model->GetFocusObject();
if (Focus && Focus->IsCamera())
{
lcCamera* Camera = (lcCamera*)Focus;
if (Item == mCameraProjectionItem)
{
Model->SetCameraOrthographic(Camera, Value == 1);
}
}
}
2023-08-04 22:26:29 +02:00
else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT)
{
lcObject* Focus = Model->GetFocusObject();
lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr;
2023-08-07 13:08:13 +02:00
if (Light)
2023-08-04 22:26:29 +02:00
{
2023-09-02 05:46:29 +02:00
if (Item == mLightTypeItem)
{
Model->SetLightType(Light, static_cast<lcLightType>(Value));
}
else if (Item == mLightAreaShapeItem)
2023-08-07 13:08:13 +02:00
{
2023-11-20 03:05:43 +01:00
Model->SetLightAreaShape(Light, static_cast<lcLightAreaShape>(Value));
2023-08-07 13:08:13 +02:00
}
2023-08-04 22:26:29 +02:00
}
}
}
2013-08-09 06:57:18 +02:00
void lcQPropertiesTree::slotColorButtonClicked()
{
int ColorIndex = gDefaultColor;
lcObject* Focus = gMainWindow->GetActiveModel()->GetFocusObject();
if (Focus && Focus->IsPiece())
2021-01-17 03:27:39 +01:00
ColorIndex = ((lcPiece*)Focus)->GetColorIndex();
2013-08-09 06:57:18 +02:00
QWidget* Button = (QWidget*)sender();
if (!Button)
return;
2023-05-16 06:02:17 +02:00
lcColorPickerPopup* Popup = new lcColorPickerPopup(Button, ColorIndex);
connect(Popup, &lcColorPickerPopup::Selected, this, &lcQPropertiesTree::slotSetValue);
Popup->setMinimumSize(qMax(300, width()), qMax(200, static_cast<int>(width() * 2 / 3)));
2013-08-09 06:57:18 +02:00
2021-07-06 02:00:41 +02:00
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
QScreen* Screen = Button->screen();
const QRect ScreenRect = Screen ? Screen->geometry() : QRect();
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
QScreen* Screen = QGuiApplication::screenAt(Button->mapToGlobal(Button->rect().bottomLeft()));
const QRect ScreenRect = Screen ? Screen->geometry() : QApplication::desktop()->geometry();
2020-12-13 01:07:56 +01:00
#else
const QRect ScreenRect = QApplication::desktop()->geometry();
#endif
2013-08-09 06:57:18 +02:00
int x = mapToGlobal(QPoint(0, 0)).x();
int y = Button->mapToGlobal(Button->rect().bottomLeft()).y();
2013-08-09 06:57:18 +02:00
if (x < ScreenRect.left())
x = ScreenRect.left();
if (y < ScreenRect.top())
y = ScreenRect.top();
2013-08-09 06:57:18 +02:00
if (x + Popup->width() > ScreenRect.right())
x = ScreenRect.right() - Popup->width();
if (y + Popup->height() > ScreenRect.bottom())
y = ScreenRect.bottom() - Popup->height();
Popup->move(QPoint(x, y));
Popup->setFocus();
Popup->show();
2013-08-09 06:57:18 +02:00
}
2023-08-27 20:17:07 +02:00
void lcQPropertiesTree::LightColorButtonClicked()
{
lcModel* Model = gMainWindow->GetActiveModel();
lcObject* Focus = Model->GetFocusObject();
lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr;
if (!Light)
return;
QColor Color = QColorDialog::getColor(lcQColorFromVector3(Light->GetColor()), this, tr("Select Light Color"));
if (!Color.isValid())
return;
Model->SetLightColor(Light, lcVector3FromQColor(Color));
QPushButton* Editor = qobject_cast<QPushButton*>(mDelegate->editor());
if (Editor)
UpdateLightColorEditor(Editor, Color);
}
2013-08-09 06:57:18 +02:00
QTreeWidgetItem *lcQPropertiesTree::addProperty(QTreeWidgetItem *parent, const QString& label, PropertyType propertyType)
{
QTreeWidgetItem *newItem;
if (parent)
newItem = new QTreeWidgetItem(parent, QStringList(label));
else
newItem = new QTreeWidgetItem(this, QStringList(label));
newItem->setData(0, PropertyTypeRole, QVariant(propertyType));
2023-10-01 22:16:26 +02:00
newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
2020-02-24 23:31:08 +01:00
newItem->setExpanded(true);
2013-08-09 06:57:18 +02:00
if (propertyType == PropertyGroup)
{
newItem->setFirstColumnSpanned(true);
newItem->setIcon(0, m_expandIcon);
}
return newItem;
}
void lcQPropertiesTree::SetEmpty()
2013-08-09 06:57:18 +02:00
{
clear();
2023-09-02 19:21:25 +02:00
mPieceAttributesItem = nullptr;
partVisibility = nullptr;
partShow = nullptr;
partHide = nullptr;
partAppearance = nullptr;
2023-09-02 19:21:25 +02:00
mPieceColorItem = nullptr;
mPieceIdItem = nullptr;
cameraPosition = nullptr;
cameraPositionX = nullptr;
cameraPositionY = nullptr;
cameraPositionZ = nullptr;
cameraTarget = nullptr;
cameraTargetX = nullptr;
cameraTargetY = nullptr;
cameraTargetZ = nullptr;
cameraUp = nullptr;
cameraUpX = nullptr;
cameraUpY = nullptr;
cameraUpZ = nullptr;
2023-09-02 19:21:25 +02:00
mCameraAttributesItem = nullptr;
mCameraProjectionItem = nullptr;
cameraFOV = nullptr;
cameraNear = nullptr;
cameraFar = nullptr;
2023-09-02 19:21:25 +02:00
mCameraNameItem = nullptr;
2023-09-02 19:21:25 +02:00
mLightColorItem = nullptr;
2023-10-01 22:16:26 +02:00
mLightPowerItem = nullptr;
2023-09-02 19:21:25 +02:00
mLightAttributesItem = nullptr;
2023-09-02 05:46:29 +02:00
mLightTypeItem = nullptr;
2023-09-02 19:21:25 +02:00
mLightNameItem = nullptr;
2023-12-17 20:37:11 +01:00
mLightAttenuationDistanceItem = nullptr;
mLightAttenuationPowerItem = nullptr;
2023-09-10 03:25:34 +02:00
mLightSpotConeAngleItem = nullptr;
mLightSpotPenumbraAngleItem = nullptr;
mLightSpotTightnessItem = nullptr;
mLightAreaShapeItem = nullptr;
2023-11-20 03:05:43 +01:00
mLightAreaGridXItem = nullptr;
mLightAreaGridYItem = nullptr;
mLightSizeXItem = nullptr;
mLightSizeYItem = nullptr;
2023-09-02 19:40:52 +02:00
mLightCastShadowItem = nullptr;
2023-09-10 03:25:34 +02:00
2023-10-01 21:49:35 +02:00
mPositionItem = nullptr;
mPositionXItem = nullptr;
mPositionYItem = nullptr;
mPositionZItem = nullptr;
mRotationItem = nullptr;
mRotationXItem = nullptr;
mRotationYItem = nullptr;
mRotationZItem = nullptr;
mWidgetMode = LC_PROPERTY_WIDGET_EMPTY;
mFocus = nullptr;
2013-08-09 06:57:18 +02:00
}
void lcQPropertiesTree::SetPiece(const lcArray<lcObject*>& Selection, lcObject* Focus)
2013-08-09 06:57:18 +02:00
{
if (mWidgetMode != LC_PROPERTY_WIDGET_PIECE)
2013-08-09 06:57:18 +02:00
{
SetEmpty();
2013-08-09 06:57:18 +02:00
2023-09-02 19:21:25 +02:00
mPieceAttributesItem = addProperty(nullptr, tr("Piece Attributes"), PropertyGroup);
mPieceIdItem = addProperty(mPieceAttributesItem, tr("Part"), PropertyPart);
mPieceColorItem = addProperty(mPieceAttributesItem, tr("Color"), PropertyPieceColor);
partVisibility = addProperty(nullptr, tr("Visible Steps"), PropertyGroup);
partShow = addProperty(partVisibility, tr("Show"), PropertyStep);
partHide = addProperty(partVisibility, tr("Hide"), PropertyStep);
2023-10-01 21:49:35 +02:00
mPositionItem = addProperty(nullptr, tr("Position"), PropertyGroup);
mPositionXItem = addProperty(mPositionItem, tr("X"), PropertyFloat);
mPositionYItem = addProperty(mPositionItem, tr("Y"), PropertyFloat);
mPositionZItem = addProperty(mPositionItem, tr("Z"), PropertyFloat);
2013-08-09 06:57:18 +02:00
2023-10-01 21:49:35 +02:00
mRotationItem = addProperty(nullptr, tr("Rotation"), PropertyGroup);
mRotationXItem = addProperty(mRotationItem, tr("X"), PropertyFloat);
mRotationYItem = addProperty(mRotationItem, tr("Y"), PropertyFloat);
mRotationZItem = addProperty(mRotationItem, tr("Z"), PropertyFloat);
2013-08-09 06:57:18 +02:00
mWidgetMode = LC_PROPERTY_WIDGET_PIECE;
2013-08-09 06:57:18 +02:00
}
lcModel* Model = gMainWindow->GetActiveModel();
lcPiece* Piece = (Focus && Focus->IsPiece()) ? (lcPiece*)Focus : nullptr;
mFocus = Piece;
lcVector3 Position;
lcMatrix33 RelativeRotation;
2023-10-01 21:49:35 +02:00
Model->GetMoveRotateTransform(Position, RelativeRotation);
2023-10-01 21:49:35 +02:00
mPositionXItem->setText(1, lcFormatValueLocalized(Position[0]));
mPositionXItem->setData(0, PropertyValueRole, Position[0]);
mPositionYItem->setText(1, lcFormatValueLocalized(Position[1]));
mPositionYItem->setData(0, PropertyValueRole, Position[1]);
mPositionZItem->setText(1, lcFormatValueLocalized(Position[2]));
mPositionZItem->setData(0, PropertyValueRole, Position[2]);
lcVector3 Rotation;
2023-10-01 21:49:35 +02:00
if (Piece)
Rotation = lcMatrix44ToEulerAngles(Piece->mModelWorld) * LC_RTOD;
else
Rotation = lcVector3(0.0f, 0.0f, 0.0f);
2023-10-01 21:49:35 +02:00
mRotationXItem->setText(1, lcFormatValueLocalized(Rotation[0]));
mRotationXItem->setData(0, PropertyValueRole, Rotation[0]);
mRotationYItem->setText(1, lcFormatValueLocalized(Rotation[1]));
mRotationYItem->setData(0, PropertyValueRole, Rotation[1]);
mRotationZItem->setText(1, lcFormatValueLocalized(Rotation[2]));
mRotationZItem->setData(0, PropertyValueRole, Rotation[2]);
lcStep Show = 0;
lcStep Hide = 0;
int ColorIndex = gDefaultColor;
PieceInfo* Info = nullptr;
if (Piece)
{
Show = Piece->GetStepShow();
Hide = Piece->GetStepHide();
2021-01-17 03:27:39 +01:00
ColorIndex = Piece->GetColorIndex();
Info = Piece->mPieceInfo;
quint32 ColorCode = lcGetColorCode(ColorIndex);
gMainWindow->PreviewPiece(Info->mFileName, ColorCode, false);
}
else
{
bool FirstPiece = true;
for (int ObjectIdx = 0; ObjectIdx < Selection.GetSize(); ObjectIdx++)
{
lcObject* Object = Selection[ObjectIdx];
2020-04-19 04:45:21 +02:00
if (!Object->IsPiece())
continue;
lcPiece* SelectedPiece = (lcPiece*)Object;
if (FirstPiece)
{
Show = SelectedPiece->GetStepShow();
Hide = SelectedPiece->GetStepHide();
2021-01-17 03:27:39 +01:00
ColorIndex = SelectedPiece->GetColorIndex();
Info = SelectedPiece->mPieceInfo;
FirstPiece = false;
}
else
{
if (SelectedPiece->GetStepShow() != Show)
Show = 0;
if (SelectedPiece->GetStepHide() != Hide)
Hide = 0;
2021-01-17 03:27:39 +01:00
if (SelectedPiece->GetColorIndex() != ColorIndex)
ColorIndex = gDefaultColor;
if (SelectedPiece->mPieceInfo != Info)
Info = nullptr;
}
}
}
partShow->setText(1, QString::number(Show));
partShow->setData(0, PropertyValueRole, Show);
partHide->setText(1, Hide == LC_STEP_MAX ? QString() : QString::number(Hide));
partHide->setData(0, PropertyValueRole, Hide);
2013-08-09 06:57:18 +02:00
QImage img(16, 16, QImage::Format_ARGB32);
img.fill(0);
lcColor* color = &gColorList[ColorIndex];
2013-08-09 06:57:18 +02:00
QPainter painter(&img);
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.setPen(Qt::darkGray);
painter.setBrush(QColor::fromRgbF(color->Value[0], color->Value[1], color->Value[2]));
painter.drawRect(0, 0, img.width() - 1, img.height() - 1);
2013-08-09 06:57:18 +02:00
painter.end();
2023-09-02 19:21:25 +02:00
mPieceColorItem->setIcon(1, QIcon(QPixmap::fromImage(img)));
mPieceColorItem->setText(1, color->Name);
mPieceColorItem->setData(0, PropertyValueRole, ColorIndex);
2013-08-09 06:57:18 +02:00
QString text = Info ? Info->m_strDescription : QString();
2023-09-02 19:21:25 +02:00
mPieceIdItem->setText(1, text);
mPieceIdItem->setToolTip(1, text);
mPieceIdItem->setData(0, PropertyValueRole, QVariant::fromValue((void*)Info));
2013-08-09 06:57:18 +02:00
}
void lcQPropertiesTree::SetCamera(lcObject* Focus)
2013-08-09 06:57:18 +02:00
{
if (mWidgetMode != LC_PROPERTY_WIDGET_CAMERA)
2013-08-09 06:57:18 +02:00
{
SetEmpty();
2013-08-09 06:57:18 +02:00
2023-09-02 19:21:25 +02:00
mCameraAttributesItem = addProperty(nullptr, tr("Camera Attributes"), PropertyGroup);
mCameraNameItem = addProperty(mCameraAttributesItem, tr("Name"), PropertyString);
mCameraProjectionItem = addProperty(mCameraAttributesItem, tr("Projection"), PropertyStringList);
cameraFOV = addProperty(mCameraAttributesItem, tr("FOV"), PropertyFloat);
cameraNear = addProperty(mCameraAttributesItem, tr("Near"), PropertyFloat);
cameraFar = addProperty(mCameraAttributesItem, tr("Far"), PropertyFloat);
cameraPosition = addProperty(nullptr, tr("Position"), PropertyGroup);
2013-08-09 06:57:18 +02:00
cameraPositionX = addProperty(cameraPosition, tr("X"), PropertyFloat);
cameraPositionY = addProperty(cameraPosition, tr("Y"), PropertyFloat);
cameraPositionZ = addProperty(cameraPosition, tr("Z"), PropertyFloat);
cameraTarget = addProperty(nullptr, tr("Target"), PropertyGroup);
2013-08-09 06:57:18 +02:00
cameraTargetX = addProperty(cameraTarget, tr("X"), PropertyFloat);
cameraTargetY = addProperty(cameraTarget, tr("Y"), PropertyFloat);
cameraTargetZ = addProperty(cameraTarget, tr("Z"), PropertyFloat);
cameraUp = addProperty(nullptr, tr("Up"), PropertyGroup);
2013-08-09 06:57:18 +02:00
cameraUpX = addProperty(cameraUp, tr("X"), PropertyFloat);
cameraUpY = addProperty(cameraUp, tr("Y"), PropertyFloat);
cameraUpZ = addProperty(cameraUp, tr("Z"), PropertyFloat);
mWidgetMode = LC_PROPERTY_WIDGET_CAMERA;
}
lcCamera* Camera = (Focus && Focus->IsCamera()) ? (lcCamera*)Focus : nullptr;
mFocus = Camera;
lcVector3 Position(0.0f, 0.0f, 0.0f);
lcVector3 Target(0.0f, 0.0f, 0.0f);
lcVector3 UpVector(0.0f, 0.0f, 0.0f);
bool Ortho = false;
float FoV = 60.0f;
float ZNear = 1.0f;
float ZFar = 100.0f;
2020-12-14 01:27:21 +01:00
QString Name;
2017-07-03 05:12:17 +02:00
if (Camera)
{
Position = Camera->mPosition;
Target = Camera->mTargetPosition;
UpVector = Camera->mUpVector;
Ortho = Camera->IsOrtho();
FoV = Camera->m_fovy;
ZNear = Camera->m_zNear;
ZFar = Camera->m_zFar;
Name = Camera->GetName();
2013-08-09 06:57:18 +02:00
}
cameraPositionX->setText(1, lcFormatValueLocalized(Position[0]));
cameraPositionX->setData(0, PropertyValueRole, Position[0]);
cameraPositionY->setText(1, lcFormatValueLocalized(Position[1]));
cameraPositionY->setData(0, PropertyValueRole, Position[1]);
cameraPositionZ->setText(1, lcFormatValueLocalized(Position[2]));
cameraPositionZ->setData(0, PropertyValueRole, Position[2]);
cameraTargetX->setText(1, lcFormatValueLocalized(Target[0]));
cameraTargetX->setData(0, PropertyValueRole, Target[0]);
cameraTargetY->setText(1, lcFormatValueLocalized(Target[1]));
cameraTargetY->setData(0, PropertyValueRole, Target[1]);
cameraTargetZ->setText(1, lcFormatValueLocalized(Target[2]));
cameraTargetZ->setData(0, PropertyValueRole, Target[2]);
cameraUpX->setText(1, lcFormatValueLocalized(UpVector[0]));
cameraUpX->setData(0, PropertyValueRole, UpVector[0]);
cameraUpY->setText(1, lcFormatValueLocalized(UpVector[1]));
cameraUpY->setData(0, PropertyValueRole, UpVector[1]);
cameraUpZ->setText(1, lcFormatValueLocalized(UpVector[2]));
cameraUpZ->setData(0, PropertyValueRole, UpVector[2]);
2023-09-02 19:21:25 +02:00
mCameraProjectionItem->setText(1, Ortho ? tr("Orthographic") : tr("Perspective"));
mCameraProjectionItem->setData(0, PropertyValueRole, Ortho);
cameraFOV->setText(1, lcFormatValueLocalized(FoV));
cameraFOV->setData(0, PropertyValueRole, FoV);
cameraNear->setText(1, lcFormatValueLocalized(ZNear));
cameraNear->setData(0, PropertyValueRole, ZNear);
cameraFar->setText(1, lcFormatValueLocalized(ZFar));
cameraFar->setData(0, PropertyValueRole, ZFar);
2023-09-02 19:21:25 +02:00
mCameraNameItem->setText(1, Name);
mCameraNameItem->setData(0, PropertyValueRole, Name);
2013-08-09 06:57:18 +02:00
}
void lcQPropertiesTree::SetLight(lcObject* Focus)
2013-08-09 06:57:18 +02:00
{
2023-08-04 22:26:29 +02:00
lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr;
QString Name = tr("Light");
2023-08-13 15:15:52 +02:00
lcLightType LightType = lcLightType::Point;
lcLightAreaShape LightAreaShape = lcLightAreaShape::Rectangle;
lcVector2 LightSize(0.0f, 0.0f);
2023-11-20 03:05:43 +01:00
lcVector2i AreaGrid(2, 2);
2023-10-01 22:16:26 +02:00
float Power = 0.0f;
2023-12-17 20:37:11 +01:00
float AttenuationDistance = 0.0f;
float AttenuationPower = 0.0f;
2023-09-02 19:40:52 +02:00
bool CastShadow = true;
2023-08-04 22:26:29 +02:00
lcVector3 Position(0.0f, 0.0f, 0.0f);
2023-08-27 20:17:07 +02:00
QColor Color(Qt::white);
2023-09-10 03:25:34 +02:00
float SpotConeAngle = 0.0f, SpotPenumbraAngle = 0.0f, SpotTightness = 0.0f;
2016-02-17 00:11:52 +01:00
2023-08-04 22:26:29 +02:00
if (Light)
{
Name = Light->GetName();
2023-09-02 19:40:52 +02:00
CastShadow = Light->GetCastShadow();
Position = Light->GetPosition();
2023-08-27 20:17:07 +02:00
Color = lcQColorFromVector3(Light->GetColor());
2023-10-01 22:16:26 +02:00
Power = Light->GetPower();
2023-12-17 20:37:11 +01:00
AttenuationDistance = Light->GetAttenuationDistance();
AttenuationPower = Light->GetAttenuationPower();
2023-09-10 03:25:34 +02:00
SpotConeAngle = Light->GetSpotConeAngle();
SpotPenumbraAngle = Light->GetSpotPenumbraAngle();
SpotTightness = Light->GetSpotTightness();
2023-09-10 03:25:34 +02:00
2023-08-13 15:15:52 +02:00
LightType = Light->GetLightType();
LightAreaShape = Light->GetAreaShape();
LightSize = Light->GetSize();
2023-11-20 03:05:43 +01:00
AreaGrid = Light->GetAreaGrid();
2023-08-04 22:26:29 +02:00
}
if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightType)
2023-08-04 22:26:29 +02:00
{
SetEmpty();
2023-08-13 15:15:52 +02:00
2023-09-02 19:21:25 +02:00
// Attributes
mLightAttributesItem = addProperty(nullptr, tr("Light Attributes"), PropertyGroup);
mLightNameItem = addProperty(mLightAttributesItem, tr("Name"), PropertyString);
mLightTypeItem = addProperty(mLightAttributesItem, tr("Type"), PropertyStringList);
2023-10-01 22:16:26 +02:00
2023-09-02 19:21:25 +02:00
mLightColorItem = addProperty(mLightAttributesItem, tr("Color"), PropertyColor);
2023-10-01 22:16:26 +02:00
mLightColorItem->setToolTip(1, tr("Color of the emitted light."));
mLightPowerItem = addProperty(mLightAttributesItem, tr("Power"), PropertyFloat);
mLightPowerItem->setToolTip(1, tr("Power of the light (Watts in Blender)."));
2023-10-01 22:16:26 +02:00
2023-09-02 19:40:52 +02:00
mLightCastShadowItem = addProperty(mLightAttributesItem, tr("Cast Shadows"), PropertyBool);
2023-08-13 15:15:52 +02:00
2023-12-17 20:37:11 +01:00
mLightAttenuationDistanceItem = addProperty(mLightAttributesItem, tr("Attenuation Distance"), PropertyFloat);
mLightAttenuationDistanceItem->setToolTip(1, tr("The distance at which the full light intensity arrives (POV-Ray only)."));
mLightAttenuationPowerItem = addProperty(mLightAttributesItem, tr("Attenuation Power"), PropertyFloat);
mLightAttenuationPowerItem->setToolTip(1, tr("Light falloff rate (POV-Ray only)."));
switch (LightType)
2023-09-10 03:25:34 +02:00
{
case lcLightType::Point:
mLightSizeXItem = addProperty(mLightAttributesItem, tr("Radius"), PropertyFloat);
mLightSizeXItem->setToolTip(1, tr("Shadow soft size (Blender only)."));
break;
2023-09-10 03:25:34 +02:00
case lcLightType::Spot:
mLightSpotConeAngleItem = addProperty(mLightAttributesItem, tr("Spot Cone Angle"), PropertyFloat);
mLightSpotConeAngleItem->setToolTip(1, tr("The angle (in degrees) of the spot light's beam."));
2023-09-10 03:25:34 +02:00
mLightSpotPenumbraAngleItem = addProperty(mLightAttributesItem, tr("Spot Penumbra Angle"), PropertyFloat);
mLightSpotPenumbraAngleItem->setToolTip(1, tr("The angle (in degrees) over which the intensity of the spot light falls off to zero."));
2023-09-10 03:25:34 +02:00
mLightSpotTightnessItem = addProperty(mLightAttributesItem, tr("Spot Tightness"), PropertyFloat);
mLightSpotTightnessItem->setToolTip(1, tr("Additional exponential spot light edge softening (POV-Ray only)."));
mLightSizeXItem = addProperty(mLightAttributesItem, tr("Radius"), PropertyFloat);
mLightSizeXItem->setToolTip(1, tr("Shadow soft size (Blender only)."));
break;
2023-08-13 15:15:52 +02:00
case lcLightType::Directional:
mLightSizeXItem = addProperty(mLightAttributesItem, tr("Angle"), PropertyFloat);
mLightSizeXItem->setToolTip(1, tr("Angular diameter of the light (Blender only)."));
break;
2023-08-13 15:15:52 +02:00
case lcLightType::Area:
mLightAreaShapeItem = addProperty(mLightAttributesItem, tr("Area Shape"), PropertyStringList);
mLightAreaShapeItem->setToolTip(1, tr("The shape of the area light."));
2023-08-13 15:15:52 +02:00
switch (LightAreaShape)
{
case lcLightAreaShape::Rectangle:
case lcLightAreaShape::Ellipse:
mLightSizeXItem = addProperty(mLightAttributesItem, tr("Area Width"), PropertyFloat);
mLightSizeXItem->setToolTip(1, tr("The width (X direction) of the area light."));
2023-08-13 15:15:52 +02:00
mLightSizeYItem = addProperty(mLightAttributesItem, tr("Area Height"), PropertyFloat);
mLightSizeYItem->setToolTip(1, tr("The height (Y direction) of the area light."));
break;
case lcLightAreaShape::Square:
case lcLightAreaShape::Disk:
mLightSizeXItem = addProperty(mLightAttributesItem, tr("Area Size"), PropertyFloat);
mLightSizeXItem->setToolTip(1, tr("The size of the area light."));
mLightSizeYItem = nullptr;
break;
case lcLightAreaShape::Count:
break;
}
2023-11-20 03:05:43 +01:00
mLightAreaGridXItem = addProperty(mLightAttributesItem, tr("Area Grid X"), PropertyInteger);
mLightAreaGridXItem->setToolTip(1, tr("Number of point sources along the X axis (POV-Ray only)."));
mLightAreaGridXItem->setData(0, PropertyRangeRole, QPointF(1, INT_MAX));
mLightAreaGridYItem = addProperty(mLightAttributesItem, tr("Area Grid Y"), PropertyInteger);
mLightAreaGridYItem->setToolTip(1, tr("Number of point sources along the Y axis (POV-Ray only)."));
mLightAreaGridYItem->setData(0, PropertyRangeRole, QPointF(1, INT_MAX));
break;
case lcLightType::Count:
break;
2023-08-04 22:26:29 +02:00
}
2023-08-13 15:15:52 +02:00
2023-10-01 21:49:35 +02:00
mPositionItem = addProperty(nullptr, tr("Position"), PropertyGroup);
mPositionXItem = addProperty(mPositionItem, tr("X"), PropertyFloat);
mPositionYItem = addProperty(mPositionItem, tr("Y"), PropertyFloat);
mPositionZItem = addProperty(mPositionItem, tr("Z"), PropertyFloat);
2023-09-02 19:21:25 +02:00
2023-10-01 21:49:35 +02:00
if (LightType != lcLightType::Point)
2023-09-02 19:21:25 +02:00
{
2023-10-01 21:49:35 +02:00
mRotationItem = addProperty(nullptr, tr("Rotation"), PropertyGroup);
mRotationXItem = addProperty(mRotationItem, tr("X"), PropertyFloat);
mRotationYItem = addProperty(mRotationItem, tr("Y"), PropertyFloat);
mRotationZItem = addProperty(mRotationItem, tr("Z"), PropertyFloat);
2023-09-02 19:21:25 +02:00
}
2023-08-04 22:26:29 +02:00
mWidgetMode = LC_PROPERTY_WIDGET_LIGHT;
2023-08-13 15:15:52 +02:00
mLightType = LightType;
2023-08-04 22:26:29 +02:00
}
mFocus = Light;
2023-10-01 21:49:35 +02:00
mPositionXItem->setText(1, lcFormatValueLocalized(Position[0]));
mPositionXItem->setData(0, PropertyValueRole, Position[0]);
mPositionYItem->setText(1, lcFormatValueLocalized(Position[1]));
mPositionYItem->setData(0, PropertyValueRole, Position[1]);
mPositionZItem->setText(1, lcFormatValueLocalized(Position[2]));
mPositionZItem->setData(0, PropertyValueRole, Position[2]);
2023-08-04 22:26:29 +02:00
2023-10-01 21:49:35 +02:00
if (LightType != lcLightType::Point)
2023-08-04 22:26:29 +02:00
{
2023-10-01 21:49:35 +02:00
lcVector3 Rotation;
if (Light)
Rotation = lcMatrix44ToEulerAngles(Light->mWorldMatrix) * LC_RTOD;
else
Rotation = lcVector3(0.0f, 0.0f, 0.0f);
mRotationXItem->setText(1, lcFormatValueLocalized(Rotation[0]));
mRotationXItem->setData(0, PropertyValueRole, Rotation[0]);
mRotationYItem->setText(1, lcFormatValueLocalized(Rotation[1]));
mRotationYItem->setData(0, PropertyValueRole, Rotation[1]);
mRotationZItem->setText(1, lcFormatValueLocalized(Rotation[2]));
mRotationZItem->setData(0, PropertyValueRole, Rotation[2]);
2023-08-04 22:26:29 +02:00
}
2023-08-27 20:17:07 +02:00
QImage ColorImage(16, 16, QImage::Format_ARGB32);
ColorImage.fill(0);
2023-08-04 22:26:29 +02:00
2023-08-27 20:17:07 +02:00
QPainter painter(&ColorImage);
2023-08-04 22:26:29 +02:00
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.setPen(Qt::darkGray);
2023-08-27 20:17:07 +02:00
painter.setBrush(Color);
painter.drawRect(0, 0, ColorImage.width() - 1, ColorImage.height() - 1);
2023-08-04 22:26:29 +02:00
painter.end();
2023-09-02 19:21:25 +02:00
mLightColorItem->setIcon(1, QIcon(QPixmap::fromImage(ColorImage)));
mLightColorItem->setText(1, Color.name().toUpper());
mLightColorItem->setData(0, PropertyValueRole, Color);
2023-08-07 13:08:13 +02:00
2023-10-01 22:16:26 +02:00
mLightPowerItem->setText(1, lcFormatValueLocalized(Power));
mLightPowerItem->setData(0, PropertyValueRole, Power);
2023-12-17 20:37:11 +01:00
mLightAttenuationDistanceItem->setText(1, lcFormatValueLocalized(AttenuationDistance));
mLightAttenuationDistanceItem->setData(0, PropertyValueRole, AttenuationDistance);
mLightAttenuationDistanceItem->setData(0, PropertyRangeRole, QPointF(0.0, FLT_MAX));
mLightAttenuationPowerItem->setText(1, lcFormatValueLocalized(AttenuationPower));
mLightAttenuationPowerItem->setData(0, PropertyValueRole, AttenuationPower);
mLightAttenuationPowerItem->setData(0, PropertyRangeRole, QPointF(0.0, FLT_MAX));
mLightTypeItem->setText(1, lcLight::GetLightTypeString(LightType));
2023-09-02 05:46:29 +02:00
mLightTypeItem->setData(0, PropertyValueRole, static_cast<int>(LightType));
2023-08-04 22:26:29 +02:00
2023-09-02 19:40:52 +02:00
mLightCastShadowItem->setCheckState(1, CastShadow ? Qt::Checked : Qt::Unchecked);
mLightCastShadowItem->setData(0, PropertyValueRole, CastShadow);
2023-08-07 13:08:13 +02:00
mLightSizeXItem->setText(1, lcFormatValueLocalized(LightSize[0]));
mLightSizeXItem->setData(0, PropertyValueRole, LightSize[0]);
if (mLightSizeYItem)
{
mLightSizeYItem->setText(1, lcFormatValueLocalized(LightSize[1]));
mLightSizeYItem->setData(0, PropertyValueRole, LightSize[1]);
}
switch (LightType)
2023-08-07 13:08:13 +02:00
{
case lcLightType::Point:
break;
2023-08-07 13:08:13 +02:00
case lcLightType::Spot:
mLightSpotConeAngleItem->setText(1, lcFormatValueLocalized(SpotConeAngle));
mLightSpotConeAngleItem->setData(0, PropertyValueRole, SpotConeAngle);
mLightSpotConeAngleItem->setData(0, PropertyRangeRole, QPointF(1.0, 180.0));
2023-08-07 13:08:13 +02:00
mLightSpotPenumbraAngleItem->setText(1, lcFormatValueLocalized(SpotPenumbraAngle));
mLightSpotPenumbraAngleItem->setData(0, PropertyValueRole, SpotPenumbraAngle);
mLightSpotPenumbraAngleItem->setData(0, PropertyRangeRole, QPointF(0.0, 180.0));
mLightSpotTightnessItem->setText(1, lcFormatValueLocalized(SpotTightness));
mLightSpotTightnessItem->setData(0, PropertyValueRole, SpotTightness);
mLightSpotTightnessItem->setData(0, PropertyRangeRole, QPointF(0.0, 100.0));
break;
case lcLightType::Directional:
break;
case lcLightType::Area:
mLightAreaShapeItem->setText(1, lcLight::GetAreaShapeString(LightAreaShape));
mLightAreaShapeItem->setData(0, PropertyValueRole, static_cast<int>(LightAreaShape));
2023-11-20 03:05:43 +01:00
mLightAreaGridXItem->setText(1, QString::number(AreaGrid.x));
mLightAreaGridXItem->setData(0, PropertyValueRole, AreaGrid.x);
mLightAreaGridYItem->setText(1, QString::number(AreaGrid.y));
mLightAreaGridYItem->setData(0, PropertyValueRole, AreaGrid.y);
break;
2023-08-07 13:08:13 +02:00
case lcLightType::Count:
break;
2023-08-04 22:26:29 +02:00
}
2023-09-02 19:21:25 +02:00
mLightNameItem->setText(1, Name);
mLightNameItem->setData(0, PropertyValueRole, QVariant::fromValue(Name));
2013-08-09 06:57:18 +02:00
}
void lcQPropertiesTree::SetMultiple()
{
if (mWidgetMode != LC_PROPERTY_WIDGET_MULTIPLE)
{
SetEmpty();
addProperty(nullptr, tr("Multiple Objects Selected"), PropertyGroup);
mWidgetMode = LC_PROPERTY_WIDGET_MULTIPLE;
}
mFocus = nullptr;
}
2013-08-09 06:57:18 +02:00
bool lcQPropertiesTree::lastColumn(int column) const
{
return header()->visualIndex(column) == columnCount() - 1;
}