From 3b9ea3ae7948652baa1acbeaf5dacb196445d603 Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Fri, 4 Aug 2023 22:26:29 +0200 Subject: [PATCH] Blender lights - view and control --- common/lc_commands.cpp | 16 ++ common/lc_commands.h | 4 + common/lc_model.cpp | 42 ++- common/lc_model.h | 5 +- common/lc_view.cpp | 30 +- common/lc_view.h | 4 + common/lc_viewmanipulator.cpp | 2 + qt/lc_qpropertiestree.cpp | 501 +++++++++++++++++++++++++++++++++- qt/lc_qpropertiestree.h | 35 +++ 9 files changed, 628 insertions(+), 11 deletions(-) diff --git a/common/lc_commands.cpp b/common/lc_commands.cpp index 3d616a98..79ff61f5 100644 --- a/common/lc_commands.cpp +++ b/common/lc_commands.cpp @@ -648,6 +648,20 @@ const lcCommand gCommands[] = QT_TRANSLATE_NOOP("Status", "Add new omni light sources to the model"), "" }, + // LC_EDIT_ACTION_AREALIGHT + { + QT_TRANSLATE_NOOP("Action", "Edit.Tool.Arealight"), + QT_TRANSLATE_NOOP("Menu", "Arealight"), + QT_TRANSLATE_NOOP("Status", "Add new arealight sources to the model - edit in Properties tab"), + "" + }, + // LC_EDIT_ACTION_SUNLIGHT + { + QT_TRANSLATE_NOOP("Action", "Edit.Tool.Sunlight"), + QT_TRANSLATE_NOOP("Menu", "Sunlight"), + QT_TRANSLATE_NOOP("Status", "Add new omnidirectional sunlight sources to the model - edit in Properties tab"), + "" + }, // LC_EDIT_ACTION_SPOTLIGHT { QT_TRANSLATE_NOOP("Action", "Edit.Tool.Spotlight"), @@ -1860,6 +1874,8 @@ const char* gToolNames[] = { QT_TRANSLATE_NOOP("Mouse", "NewPiece"), // lcTool::Insert QT_TRANSLATE_NOOP("Mouse", "NewPointLight"), // lcTool::Light + QT_TRANSLATE_NOOP("Mouse", "NewAreaLight"), // lcTool::AreaLight + QT_TRANSLATE_NOOP("Mouse", "NewSunLight"), // lcTool::SunLight QT_TRANSLATE_NOOP("Mouse", "NewSpotLight"), // lcTool::SpotLight QT_TRANSLATE_NOOP("Mouse", "NewCamera"), // lcTool::Camera QT_TRANSLATE_NOOP("Mouse", "Select"), // lcTool::Select diff --git a/common/lc_commands.h b/common/lc_commands.h index f49d28fc..6db95a22 100644 --- a/common/lc_commands.h +++ b/common/lc_commands.h @@ -99,6 +99,8 @@ enum lcCommandId LC_EDIT_ACTION_FIRST, LC_EDIT_ACTION_INSERT = LC_EDIT_ACTION_FIRST, LC_EDIT_ACTION_LIGHT, + LC_EDIT_ACTION_AREALIGHT, + LC_EDIT_ACTION_SUNLIGHT, LC_EDIT_ACTION_SPOTLIGHT, LC_EDIT_ACTION_CAMERA, LC_EDIT_ACTION_SELECT, @@ -299,6 +301,8 @@ enum class lcTool { Insert, Light, + AreaLight, + SunLight, SpotLight, Camera, Select, diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 843119b5..6069cfad 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -571,6 +571,15 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project) } else if (Token == QLatin1String("LIGHT")) { + if (!Light) + Light = new lcLight(0.0f, 0.0f, 0.0f); + + if (Light->ParseLDrawLine(LineStream)) + { + Light->CreateName(mLights); + mLights.Add(Light); + Light = nullptr; + } } else if (Token == QLatin1String("GROUP")) { @@ -2949,6 +2958,15 @@ void lcModel::SetSelectedPiecesStepHide(lcStep Step) } } +void lcModel::UpdateLight(lcLight* Light, const lcLightProperties Props, int Property) +{ + Light->UpdateLight(mCurrentStep, Props, Property); + + SaveCheckpoint(tr("Update Light")); + UpdateAllViews(); + gMainWindow->UpdateSelectedObjects(false); +} + void lcModel::SetCameraOrthographic(lcCamera* Camera, bool Ortho) { if (Camera->IsOrtho() == Ortho) @@ -3011,6 +3029,19 @@ void lcModel::SetCameraName(lcCamera* Camera, const QString& Name) gMainWindow->UpdateCameraMenu(); } +void lcModel::SetLightName(lcLight* Light, const QString &Name) +{ + if (Light->GetName() == Name) + return; + + Light->SetName(Name); + + SaveCheckpoint(tr("Renaming Light")); + gMainWindow->UpdateSelectedObjects(false); + UpdateAllViews(); + gMainWindow->UpdateCameraMenu(); +} + bool lcModel::AnyPiecesSelected() const { for (const lcPiece* Piece : mPieces) @@ -3955,6 +3986,8 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept) { case lcTool::Insert: case lcTool::Light: + case lcTool::AreaLight: + case lcTool::SunLight: break; case lcTool::SpotLight: @@ -4034,17 +4067,20 @@ void lcModel::PointLightToolClicked(const lcVector3& Position) SaveCheckpoint(tr("New Light")); } -void lcModel::BeginSpotLightTool(const lcVector3& Position, const lcVector3& Target) +void lcModel::BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, int LightType) { - lcLight* Light = new lcLight(Position[0], Position[1], Position[2], Target[0], Target[1], Target[2]); + lcLight* Light = new lcLight(Position[0], Position[1], Position[2], Target[0], Target[1], Target[2], LightType); + Light->CreateName(mLights); mLights.Add(Light); mMouseToolDistance = Target; ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_TARGET, false); + QString light(LightType == LC_AREALIGHT ? "Arealight " : LightType == LC_SUNLIGHT ? "Sunlight " : "Spotlight "); + SaveCheckpoint(tr("%1").arg(light)); } -void lcModel::UpdateSpotLightTool(const lcVector3& Position) +void lcModel::UpdateDirectionalLightTool(const lcVector3& Position) { lcLight* Light = mLights[mLights.GetSize() - 1]; diff --git a/common/lc_model.h b/common/lc_model.h index 5ce41599..e92b1c03 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -302,8 +302,9 @@ public: void EndMouseTool(lcTool Tool, bool Accept); void InsertPieceToolClicked(const lcMatrix44& WorldMatrix); void PointLightToolClicked(const lcVector3& Position); + void BeginDirectionalLightTool(const lcVector3& Position, const lcVector3& Target, int LightType); + void UpdateDirectionalLightTool(const lcVector3& Position); void BeginSpotLightTool(const lcVector3& Position, const lcVector3& Target); - void UpdateSpotLightTool(const lcVector3& Position); void BeginCameraTool(const lcVector3& Position, const lcVector3& Target); void UpdateCameraTool(const lcVector3& Position); void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag); @@ -341,6 +342,8 @@ public: void SetCameraZNear(lcCamera* Camera, float ZNear); void SetCameraZFar(lcCamera* Camera, float ZFar); void SetCameraName(lcCamera* Camera, const QString& Name); + void SetLightName(lcLight* Light, const QString& Name); + void UpdateLight(lcLight* Light, const lcLightProperties Props, int Property); void ShowPropertiesDialog(); void ShowSelectByNameDialog(); diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 71d6c93c..370fe84a 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -3,6 +3,7 @@ #include "lc_viewwidget.h" #include #include "lc_mainwindow.h" +#include "light.h" #include "camera.h" #include "texfont.h" #include "lc_texture.h" @@ -1596,6 +1597,8 @@ lcTrackTool lcView::GetOverrideTrackTool(Qt::MouseButton Button) const { lcTrackTool::Insert, // lcTool::Insert lcTrackTool::PointLight, // lcTool::Light + lcTrackTool::AreaLight, // lcTool::AreaLight + lcTrackTool::SunLight, // lcTool::SunLight lcTrackTool::SpotLight, // lcTool::SpotLight lcTrackTool::Camera, // lcTool::Camera lcTrackTool::Select, // lcTool::Select @@ -1867,6 +1870,8 @@ lcCursor lcView::GetCursor() const lcCursor::Select, // lcTrackTool::None lcCursor::Brick, // lcTrackTool::Insert lcCursor::Light, // lcTrackTool::PointLight + lcCursor::Arealight, // lcTrackTool::AreaLight + lcCursor::Sunlight, // lcTrackTool::SunLight lcCursor::Spotlight, // lcTrackTool::SpotLight lcCursor::Camera, // lcTrackTool::Camera lcCursor::Select, // lcTrackTool::Select @@ -1921,6 +1926,8 @@ void lcView::SetCursor(lcCursor CursorType) { 0, 0, "" }, // lcCursor::Default { 8, 3, ":/resources/cursor_insert" }, // lcCursor::Brick { 15, 15, ":/resources/cursor_light" }, // lcCursor::Light + { 15, 15, ":/resources/cursor_arealight" }, // lcCursor::Arealight + { 15, 15, ":/resources/cursor_sunlight" }, // lcCursor::Sunlight { 7, 10, ":/resources/cursor_spotlight" }, // lcCursor::Spotlight { 15, 9, ":/resources/cursor_camera" }, // lcCursor::Camera { 0, 2, ":/resources/cursor_select" }, // lcCursor::Select @@ -1972,6 +1979,8 @@ lcTool lcView::GetCurrentTool() const lcTool::Select, // lcTrackTool::None lcTool::Insert, // lcTrackTool::Insert lcTool::Light, // lcTrackTool::PointLight + lcTool::AreaLight, // lcTrackTool::AreaLight + lcTool::SunLight, // lcTrackTool::SunLight lcTool::SpotLight, // lcTrackTool::SpotLight lcTool::Camera, // lcTrackTool::Camera lcTool::Select, // lcTrackTool::Select @@ -2036,6 +2045,14 @@ void lcView::UpdateTrackTool() NewTrackTool = lcTrackTool::PointLight; break; + case lcTool::AreaLight: + NewTrackTool = lcTrackTool::AreaLight;; + break; + + case lcTool::SunLight: + NewTrackTool = lcTrackTool::SunLight; + break; + case lcTool::SpotLight: NewTrackTool = lcTrackTool::SpotLight; break; @@ -2261,11 +2278,14 @@ void lcView::StartTracking(lcTrackButton TrackButton) case lcTool::Light: break; + case lcTool::AreaLight: + case lcTool::SunLight: case lcTool::SpotLight: { lcVector3 Position = GetCameraLightInsertPosition(); lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f); - ActiveModel->BeginSpotLightTool(Position, Target); + int LightType = Tool == lcTool::AreaLight ? LC_AREALIGHT : Tool == lcTool::SunLight ? LC_SUNLIGHT : LC_SPOTLIGHT; + ActiveModel->BeginDirectionalLightTool(Position, Target, LightType); } break; @@ -2325,6 +2345,8 @@ void lcView::StopTracking(bool Accept) case lcTool::Light: break; + case lcTool::AreaLight: + case lcTool::SunLight: case lcTool::SpotLight: case lcTool::Camera: ActiveModel->EndMouseTool(Tool, Accept); @@ -2452,6 +2474,8 @@ void lcView::OnButtonDown(lcTrackButton TrackButton) } break; + case lcTrackTool::AreaLight: + case lcTrackTool::SunLight: case lcTrackTool::SpotLight: case lcTrackTool::Camera: StartTracking(TrackButton); @@ -2689,8 +2713,10 @@ void lcView::OnMouseMove() case lcTrackTool::PointLight: break; + case lcTrackTool::AreaLight: + case lcTrackTool::SunLight: case lcTrackTool::SpotLight: - ActiveModel->UpdateSpotLightTool(GetCameraLightInsertPosition()); + ActiveModel->UpdateDirectionalLightTool(GetCameraLightInsertPosition()); break; case lcTrackTool::Camera: diff --git a/common/lc_view.h b/common/lc_view.h index e7c8d27f..0227be62 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -18,6 +18,8 @@ enum class lcCursor Default, Brick, Light, + Arealight, + Sunlight, Spotlight, Camera, Select, @@ -51,6 +53,8 @@ enum class lcTrackTool None, Insert, PointLight, + AreaLight, + SunLight, SpotLight, Camera, Select, diff --git a/common/lc_viewmanipulator.cpp b/common/lc_viewmanipulator.cpp index e26ce898..84ef75db 100644 --- a/common/lc_viewmanipulator.cpp +++ b/common/lc_viewmanipulator.cpp @@ -674,6 +674,8 @@ bool lcViewManipulator::IsTrackToolAllowed(lcTrackTool TrackTool, quint32 Allowe case lcTrackTool::None: case lcTrackTool::Insert: case lcTrackTool::PointLight: + case lcTrackTool::AreaLight: + case lcTrackTool::SunLight: case lcTrackTool::SpotLight: case lcTrackTool::Camera: case lcTrackTool::Select: diff --git a/qt/lc_qpropertiestree.cpp b/qt/lc_qpropertiestree.cpp index a19c3f9b..7c562a1d 100644 --- a/qt/lc_qpropertiestree.cpp +++ b/qt/lc_qpropertiestree.cpp @@ -160,7 +160,7 @@ void lcQPropertiesTreeDelegate::paint(QPainter *painter, const QStyleOptionViewI QColor color = static_cast(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt)); painter->save(); painter->setPen(QPen(color)); - + if (!m_treeWidget || (!m_treeWidget->lastColumn(index.column()) && hasValue)) { int right = (option.direction == Qt::LeftToRight) ? option.rect.right() : option.rect.left(); @@ -457,6 +457,31 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) return editor; } + case PropertyFloatLightSpotSize: + { + QLineEdit *editor = new QLineEdit(parent); + float value = item->data(0, PropertyValueRole).toFloat(); + + editor->setValidator(new QDoubleValidator(1.0, 180.0,1, editor)); + editor->setText(lcFormatValueLocalized(value)); + editor->setToolTip(tr("Angle of the spotlight beam.")); + + connect(editor, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed())); + return editor; + } + + case PropertyFloatReadOnly: + { + QLineEdit *editor = new QLineEdit(parent); + float value = item->data(0, PropertyValueRole).toFloat(); + + editor->setText(lcFormatValueLocalized(value)); + editor->setReadOnly(true); + editor->setToolTip(tr("Property is read only")); + + return editor; + } + case PropertyStep: { QLineEdit* Editor = new QLineEdit(parent); @@ -495,6 +520,49 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) return editor; } + case PropertyStringLightReadOnly: + { + QLineEdit *editor = new QLineEdit(parent); + const char *value = (const char*)item->data(0, PropertyValueRole).value(); + + editor->setText(value); + editor->setReadOnly(true); + editor->setToolTip(tr("Property is read only")); + + return editor; + } + + case PropertyLightShape: + { + QComboBox *editor = new QComboBox(parent); + + editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); + editor->setMinimumContentsLength(1); + + QStringList shapes = { "Square", "Disk", "Rectangle", "Ellipse"}; + for (int i = 0; i < shapes.size(); i++) + editor->addItem(shapes.at(i), QVariant::fromValue(i)); + + int value = item->data(0, PropertyValueRole).toInt(); + editor->setCurrentIndex(value); + + connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); + + return editor; + } + + case PropertyLightColor: + { + QPushButton *editor = new QPushButton(parent); + QColor value = item->data(0, PropertyValueRole).value(); + + updateLightColorEditor(editor, value); + + connect(editor, SIGNAL(clicked()), this, SLOT(slotColorButtonClicked())); + + return editor; + } + case PropertyColor: { QPushButton *editor = new QPushButton(parent); @@ -567,10 +635,28 @@ void lcQPropertiesTree::updateColorEditor(QPushButton *editor, int value) const editor->setText(color->Name); } +void lcQPropertiesTree::updateLightColorEditor(QPushButton *editor, QColor color) const +{ + QImage img(12, 12, QImage::Format_ARGB32); + img.fill(0); + + QPainter painter(&img); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.setPen(Qt::darkGray); + painter.setBrush(color); + painter.drawRect(0, 0, img.width() - 1, img.height() - 1); + painter.end(); + + editor->setStyleSheet("Text-align:left"); + editor->setIcon(QPixmap::fromImage(img)); + editor->setText(color.name().toUpper()); +} + void lcQPropertiesTree::slotToggled(bool Value) { QTreeWidgetItem* Item = m_delegate->editedItem(); lcModel* Model = gMainWindow->GetActiveModel(); + lcObject* Focus = Model->GetFocusObject(); if (mWidgetMode == LC_PROPERTY_WIDGET_CAMERA) { @@ -586,6 +672,30 @@ void lcQPropertiesTree::slotToggled(bool Value) } } } + else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT) + { + lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; + + if (Light) + { + lcLightProperties Props = Light->GetLightProperties(); + if (Item == lightEnableCutoff) + { + Props.mEnableCutoff = Value; + Model->UpdateLight(Light, Props, LC_LIGHT_USE_CUTOFF); + } + else if (Item == lightPOVRay) + { + Props.mPOVRayLight = Value; + Model->UpdateLight(Light, Props, LC_LIGHT_POVRAY); + } + else if (Item == lightShadowless) + { + Props.mShadowless = Value; + Model->UpdateLight(Light, Props, LC_LIGHT_SHADOWLESS); + } + } + } } void lcQPropertiesTree::slotReturnPressed() @@ -744,6 +854,102 @@ void lcQPropertiesTree::slotReturnPressed() } } } + else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT) + { + lcLight* Light = (mFocus && mFocus->IsLight()) ? (lcLight*)mFocus : nullptr; + + if (Light) + { + lcLightProperties Props = Light->GetLightProperties(); + + QString Name = Light->GetName(); + + if (Item == lightPositionX || Item == lightPositionY || Item == lightPositionZ) + { + lcVector3 Center = Light->mPosition; + lcVector3 Position = Center; + float Value = lcParseValueLocalized(Editor->text()); + if (Item == lightPositionX) + Position[0] = Value; + else if (Item == lightPositionY) + Position[1] = Value; + else if (Item == lightPositionZ) + Position[2] = Value; + + lcVector3 Distance = Position - Center; + + Model->MoveSelectedObjects(Distance, Distance, false, false, true, true); + } + else if (Item == lightTargetX || Item == lightTargetY || Item == lightTargetZ) + { + lcVector3 Center = Light->mTargetPosition; + lcVector3 Position = Center; + float Value = lcParseValueLocalized(Editor->text()); + if (Item == lightTargetX) + Position[0] = Value; + else if (Item == lightTargetY) + Position[1] = Value; + else if (Item == lightTargetZ) + Position[2] = Value; + + lcVector3 Distance = Position - Center; + + Model->MoveSelectedObjects(Distance, Distance, false, false, true, true); + } + else if (Item == lightColorR || Item == lightColorG || Item == lightColorB) + { + float Value = lcParseValueLocalized(Editor->text()); + if (Item == lightColorR) + Props.mLightColor[0] = Value; + else if (Item == lightColorG) + Props.mLightColor[2] = Value; + else if (Item == lightColorB) + Props.mLightColor[1] = Value; + + Model->UpdateLight(Light, Props, LC_LIGHT_COLOR); + } + else if (Item == lightFactorA || Item == lightFactorB) + { + float Value = lcParseValueLocalized(Editor->text()); + if (Item == lightFactorA) + Props.mLightFactor[0] = Value; + else if (Item == lightFactorB) + Props.mLightFactor[1] = Value; + + Model->UpdateLight(Light, Props, LC_LIGHT_FACTOR); + } + else if (Item == lightSpecular) + { + Props.mLightSpecular = lcParseValueLocalized(Editor->text()); + + Model->UpdateLight(Light, Props, LC_LIGHT_SPECULAR); + } + else if (Item == lightExponent) + { + Props.mSpotExponent = lcParseValueLocalized(Editor->text()); + + Model->UpdateLight(Light, Props, LC_LIGHT_EXPONENT); + } + else if (Item == lightCutoff) + { + Props.mSpotCutoff = lcParseValueLocalized(Editor->text()); + + Model->UpdateLight(Light, Props, LC_LIGHT_CUTOFF); + } + else if (Item == lightSpotSize) + { + Props.mSpotSize = lcParseValueLocalized(Editor->text()); + + Model->UpdateLight(Light, Props, LC_LIGHT_SPOT_SIZE); + } + else if (Item == lightName) + { + QString Value = Editor->text(); + + Model->SetLightName(Light, Value.toLocal8Bit().data()); + } + } + } } void lcQPropertiesTree::slotSetValue(int Value) @@ -775,6 +981,37 @@ void lcQPropertiesTree::slotSetValue(int Value) gMainWindow->PreviewPiece(Info->mFileName, ColorCode, false); } } + else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT) + { + lcObject* Focus = Model->GetFocusObject(); + + lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; + + if (Light && Item == lightShape) + { + lcLightProperties Props = Light->GetLightProperties(); + Props.mLightShape = static_cast(Value); + Model->UpdateLight(Light, Props, LC_LIGHT_SHAPE); + } + } +} + +void lcQPropertiesTree::slotSetColorValue(QColor Value) +{ + lcModel* Model = gMainWindow->GetActiveModel(); + lcObject* Focus = Model->GetFocusObject(); + lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; + if (Light) + { + float r = Value.red(); + float g = Value.green(); + float b = Value.blue(); + lcVector3 Color(r/255, g/255, b/255); + + lcLightProperties Props = Light->GetLightProperties(); + Props.mLightColor = Color; + Model->UpdateLight(Light, Props, LC_LIGHT_COLOR); + } } void lcQPropertiesTree::slotColorButtonClicked() @@ -882,6 +1119,31 @@ void lcQPropertiesTree::SetEmpty() cameraFar = nullptr; cameraName = nullptr; + lightPosition = nullptr; + lightPositionX = nullptr; + lightPositionY = nullptr; + lightPositionZ = nullptr; + lightTarget = nullptr; + lightTargetX = nullptr; + lightTargetY = nullptr; + lightTargetZ = nullptr; + lightColor = nullptr; + lightColorIcon = nullptr; + lightColorR = nullptr; + lightColorG = nullptr; + lightColorB = nullptr; + lightProperties = nullptr; + lightSpecular = nullptr; + lightCutoff = nullptr; + lightEnableCutoff = nullptr; + lightExponent = nullptr; + lightType = nullptr; + lightFactorA = nullptr; + lightFactorB = nullptr; + lightName = nullptr; + lightSpotSize = nullptr; + lightShape = nullptr; + mWidgetMode = LC_PROPERTY_WIDGET_EMPTY; mFocus = nullptr; } @@ -1110,12 +1372,241 @@ void lcQPropertiesTree::SetCamera(lcObject* Focus) void lcQPropertiesTree::SetLight(lcObject* Focus) { - Q_UNUSED(Focus); + lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr; - SetEmpty(); - mFocus = nullptr; + QString Name = tr("Light"); + QString FactorALabel = tr("FactorA"); + QString ExponentLabel = tr("Exponent"); + QString Type, Shape, FactorAToolTip, FactorBToolTip; + lcLightType LightIndex = LC_UNDEFINED_LIGHT; + lcLightShape ShapeIndex = LC_LIGHT_SHAPE_UNDEFINED; + float SpotSize = 0.0f; + float Specular = 0.0f; + float Cutoff = 0.0f; + float Exponent = 0.0f; + bool EnableCutoff = false; + PropertyType TargetProperty = PropertyFloat; + lcVector3 Position(0.0f, 0.0f, 0.0f); + lcVector3 Target(0.0f, 0.0f, 0.0f); + lcVector3 Color(0.0f, 0.0f, 0.0f); + lcVector2 Factor(0.0f, 0.0f); - // todo: light properties + if (Light) + { + Name = Light->GetName(); + + Position = Light->mPosition; // normalizeDegrees(Light->mPosition); + Target = Light->mTargetPosition; // normalizeDegrees(Light->mTargetPosition); + Color = Light->mLightColor; + Factor = Light->mLightFactor; + LightIndex = static_cast(Light->mLightType); + + switch(LightIndex) + { + case LC_POINTLIGHT: + Type = QLatin1String("Point"); + FactorALabel = tr("Radius (m)"); + FactorAToolTip = tr("Shadow soft size - Light size for shadow sampling"); + break; + case LC_AREALIGHT: + Type = QLatin1String("Area"); + FactorALabel = tr("Width (X)"); + FactorAToolTip = tr("Size of the area of the area light. X direction size for rectangular shapes"); + FactorBToolTip = tr("Size of the area of the area light. Y direction size for rectangular shapes"); + break; + case LC_SUNLIGHT: + Type = QLatin1String("Sun"); + FactorALabel = tr("Angle (°)"); + FactorAToolTip = tr("Angular diamater of the sun as seen from the Earth"); + break; + case LC_SPOTLIGHT: + Type = QLatin1String("Spot"); + FactorALabel = tr("Radius (m)"); + FactorAToolTip = tr("Shadow soft size - Light size for shadow sampling"); + FactorBToolTip = tr("Shadow blend - The softness of the spotlight edge"); + break; + default: + Type = QLatin1String("Undefined"); + FactorALabel = tr("FactorA"); + break; + } + + ShapeIndex = static_cast(Light->mLightShape); + switch(ShapeIndex) + { + case LC_LIGHT_SHAPE_SQUARE: + Shape = QLatin1String("Square"); + break; + case LC_LIGHT_SHAPE_DISK: + Shape = QLatin1String("Disk"); + break; + case LC_LIGHT_SHAPE_RECTANGLE: + Shape = QLatin1String("Rectangle"); + break; + case LC_LIGHT_SHAPE_ELLIPSE: + Shape = QLatin1String("Ellipse"); + break; + default: + break; + } + + Specular = Light->mLightSpecular; + Exponent = Light->mSpotExponent; + ExponentLabel = LightIndex ? LightIndex == LC_SUNLIGHT ? tr("Strength") : tr("Power") : tr("Exponent"); + Cutoff = Light->mSpotCutoff; + EnableCutoff = Light->mEnableCutoff; + TargetProperty = Light->mLightType > LC_POINTLIGHT ? PropertyFloat : PropertyFloatReadOnly; + SpotSize = Light->mSpotSize; + } + + if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightIndex || mLightShape != ShapeIndex) + { + SetEmpty(); + // Position + lightPosition = addProperty(nullptr, tr("Position"), PropertyGroup); + lightPositionX = addProperty(lightPosition, tr("X"), PropertyFloat); + lightPositionY = addProperty(lightPosition, tr("Y"), PropertyFloat); + lightPositionZ = addProperty(lightPosition, tr("Z"), PropertyFloat); + // Target Position + if (LightIndex != LC_POINTLIGHT) + { + lightTarget = addProperty(nullptr, tr("Target"), PropertyGroup); + lightTargetX = addProperty(lightTarget, tr("X"), TargetProperty); + lightTargetY = addProperty(lightTarget, tr("Y"), TargetProperty); + lightTargetZ = addProperty(lightTarget, tr("Z"), TargetProperty); + } + // Ambient Colour + lightColor = addProperty(nullptr, tr("Color"), PropertyGroup); + lightColorIcon = addProperty(lightColor, tr("Name"), PropertyLightColor); + lightColorR = addProperty(lightColor, tr("Red"), PropertyFloat); + lightColorG = addProperty(lightColor, tr("Green"), PropertyFloat); + lightColorB = addProperty(lightColor, tr("Blue"), PropertyFloat); + // Properties + lightProperties = addProperty(nullptr, tr("Properties"), PropertyGroup); + lightType = addProperty(lightProperties, tr("Type"), PropertyStringLightReadOnly); + lightExponent = addProperty(lightProperties, ExponentLabel, PropertyFloat); + lightFactorA = addProperty(lightProperties, FactorALabel, PropertyFloat); + if (LightIndex == LC_AREALIGHT) + { + if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE) + lightFactorB = addProperty(lightProperties, tr("Height (Y)"), PropertyFloat); + lightShape = addProperty(lightProperties, tr("Shape"), PropertyLightShape); + } + else if (LightIndex == LC_SPOTLIGHT) + { + lightFactorB = addProperty(lightProperties, tr("Spot Blend"), PropertyFloat); + lightSpotSize = addProperty(lightProperties, tr("Spot Size (°)"), PropertyFloatLightSpotSize); + } + if (LightIndex != LC_SUNLIGHT) + { + lightEnableCutoff = addProperty(lightProperties, tr("Cutoff"), PropertyBool); + lightCutoff = addProperty(lightProperties, tr("Cutoff Distance"), PropertyFloat); + } + lightSpecular = addProperty(lightProperties, tr("Specular"), PropertyFloat); + lightName = addProperty(lightProperties, tr("Name"), PropertyString); + + mWidgetMode = LC_PROPERTY_WIDGET_LIGHT; + mLightType = LightIndex; + mLightShape = ShapeIndex; + } + + mFocus = Light; + + lightPositionX->setText(1, lcFormatValueLocalized(Position[0])); + lightPositionX->setData(0, PropertyValueRole, Position[0]); + lightPositionY->setText(1, lcFormatValueLocalized(Position[1])); + lightPositionY->setData(0, PropertyValueRole, Position[1]); + lightPositionZ->setText(1, lcFormatValueLocalized(Position[2])); + lightPositionZ->setData(0, PropertyValueRole, Position[2]); + + if (LightIndex != LC_POINTLIGHT) + { + lightTargetX->setText(1, lcFormatValueLocalized(Target[0])); + lightTargetX->setData(0, PropertyValueRole, Target[0]); + lightTargetY->setText(1, lcFormatValueLocalized(Target[1])); + lightTargetY->setData(0, PropertyValueRole, Target[1]); + lightTargetZ->setText(1, lcFormatValueLocalized(Target[2])); + lightTargetZ->setData(0, PropertyValueRole, Target[2]); + } + + QImage img(16, 16, QImage::Format_ARGB32); + img.fill(0); + + QColor RgbColor = QColor::fromRgb(int(Color[1]*255), int(Color[1]*255), int(Color[2]*255)); + + QPainter painter(&img); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.setPen(Qt::darkGray); + painter.setBrush(RgbColor); + painter.drawRect(0, 0, img.width() - 1, img.height() - 1); + painter.end(); + + lightColorIcon->setIcon(1, QIcon(QPixmap::fromImage(img))); + lightColorIcon->setText(1, RgbColor.name().toUpper()); + lightColorIcon->setData(0, PropertyValueRole, RgbColor); + + lightColorR->setText(1, lcFormatValueLocalized(Color[0])); + lightColorR->setData(0, PropertyValueRole, Color[0]); + lightColorR->setToolTip(1, tr("Red color component - use .0 - 1 format")); + lightColorG->setText(1, lcFormatValueLocalized(Color[1])); + lightColorG->setData(0, PropertyValueRole, Color[1]); + lightColorG->setToolTip(1, tr("Green color component - use .0 - 1 format")); + lightColorB->setText(1, lcFormatValueLocalized(Color[2])); + lightColorB->setData(0, PropertyValueRole, Color[2]); + lightColorB->setToolTip(1, tr("Blue color component - use .0 - 1 format")); + + lightType->setText(1, Type); + lightType->setData(0, PropertyValueRole, Type); + + lightExponent->setText(1, lcFormatValueLocalized(Exponent)); + lightExponent->setData(0, PropertyValueRole, Exponent); + lightExponent->setToolTip(1, tr("Intensity of the light in Watts.")); + + lightFactorA->setText(1, lcFormatValueLocalized(Factor[0])); + lightFactorA->setData(0, PropertyValueRole, Factor[0]); + lightFactorA->setToolTip(1, FactorAToolTip); + + if (LightIndex == LC_AREALIGHT) + { + if (ShapeIndex == LC_LIGHT_SHAPE_RECTANGLE || ShapeIndex == LC_LIGHT_SHAPE_ELLIPSE) + { + lightFactorB->setText(1, lcFormatValueLocalized(Factor[1])); + lightFactorB->setData(0, PropertyValueRole, Factor[1]); + lightFactorB->setToolTip(1, FactorBToolTip); + } + + lightShape->setText(1, Shape); + lightShape->setData(0, PropertyValueRole, ShapeIndex); + lightShape->setToolTip(1, tr("Shape of the arealight.")); + + } + else if (LightIndex == LC_SPOTLIGHT) + { + lightFactorB->setText(1, lcFormatValueLocalized(Factor[1])); + lightFactorB->setData(0, PropertyValueRole, Factor[1]); + lightFactorB->setToolTip(1, FactorBToolTip); + + lightSpotSize->setText(1, lcFormatValueLocalized(SpotSize)); + lightSpotSize->setData(0, PropertyValueRole, SpotSize); + lightSpotSize->setToolTip(1, tr("Angle of the spotlight beam.")); + } + + if (LightIndex != LC_SUNLIGHT) + { + lightEnableCutoff->setText(1, EnableCutoff ? "True" : "False"); + lightEnableCutoff->setData(0, PropertyValueRole, EnableCutoff); + + lightCutoff->setText(1, lcFormatValueLocalized(Cutoff)); + lightCutoff->setData(0, PropertyValueRole, Cutoff); + lightCutoff->setToolTip(1, tr("Distance at which the light influence will be set to 0.")); + } + + lightSpecular->setText(1, lcFormatValueLocalized(Specular)); + lightSpecular->setData(0, PropertyValueRole, Specular); + lightSpecular->setToolTip(1, tr("Specular reflection multiplier factor.")); + + lightName->setText(1, Name); + lightName->setData(0, PropertyValueRole, QVariant::fromValue(Name)); } void lcQPropertiesTree::SetMultiple() diff --git a/qt/lc_qpropertiestree.h b/qt/lc_qpropertiestree.h index 7ea77165..5b06a330 100644 --- a/qt/lc_qpropertiestree.h +++ b/qt/lc_qpropertiestree.h @@ -44,8 +44,13 @@ public: PropertyGroup, PropertyBool, PropertyFloat, + PropertyFloatReadOnly, + PropertyFloatLightSpotSize, PropertyStep, PropertyString, + PropertyStringLightReadOnly, + PropertyLightShape, + PropertyLightColor, PropertyColor, PropertyPart }; @@ -55,12 +60,14 @@ protected slots: void slotReturnPressed(); void slotSetValue(int value); void slotColorButtonClicked(); + void slotSetColorValue(QColor Value); protected: void keyPressEvent(QKeyEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void updateColorEditor(QPushButton *editor, int value) const; + void updateLightColorEditor(QPushButton *editor, QColor color) const; QTreeWidgetItem *addProperty(QTreeWidgetItem *parent, const QString& label, PropertyType propertyType); @@ -72,6 +79,9 @@ protected: void getPartProperties(lcPartProperties *properties); + int mLightType; + int mLightShape; + lcPropertyWidgetMode mWidgetMode; lcObject* mFocus; @@ -113,6 +123,31 @@ protected: QTreeWidgetItem *cameraNear; QTreeWidgetItem *cameraFar; QTreeWidgetItem *cameraName; + + QTreeWidgetItem *lightPosition; + QTreeWidgetItem *lightPositionX; + QTreeWidgetItem *lightPositionY; + QTreeWidgetItem *lightPositionZ; + QTreeWidgetItem *lightTarget; + QTreeWidgetItem *lightTargetX; + QTreeWidgetItem *lightTargetY; + QTreeWidgetItem *lightTargetZ; + QTreeWidgetItem *lightColor; + QTreeWidgetItem *lightColorIcon; + QTreeWidgetItem *lightColorR; + QTreeWidgetItem *lightColorG; + QTreeWidgetItem *lightColorB; + QTreeWidgetItem *lightProperties; + QTreeWidgetItem *lightSpecular; + QTreeWidgetItem *lightCutoff; + QTreeWidgetItem *lightEnableCutoff; + QTreeWidgetItem *lightExponent; + QTreeWidgetItem *lightType; + QTreeWidgetItem *lightSpotSize; + QTreeWidgetItem *lightShape; + QTreeWidgetItem *lightFactorA; + QTreeWidgetItem *lightFactorB; + QTreeWidgetItem *lightName; }; class lcQPropertiesTreeDelegate : public QItemDelegate