3D Preview

3D Preview - restore doc format
This commit is contained in:
Trevor SANDY 2020-10-03 12:02:27 +02:00
parent 8223b61a24
commit a239e504ec
24 changed files with 1811 additions and 305 deletions

View file

@ -9,6 +9,7 @@
#include "lc_partselectionwidget.h"
#include "lc_shortcuts.h"
#include "view.h"
#include "lc_previewwidget.h"
lcApplication* gApplication;
@ -43,6 +44,17 @@ void lcPreferences::LoadDefaults()
mAutoLoadMostRecent = lcGetProfileInt(LC_PROFILE_AUTOLOAD_MOSTRECENT);
mRestoreTabLayout = lcGetProfileInt(LC_PROFILE_RESTORE_TAB_LAYOUT);
mColorTheme = static_cast<lcColorTheme>(lcGetProfileInt(LC_PROFILE_COLOR_THEME));
mPreviewActiveColor = lcGetProfileInt(LC_PROFILE_PREVIEW_ACTIVE_COLOR);
mPreviewViewSphereEnabled = lcGetProfileInt(LC_PROFILE_PREVIEW_VIEW_SPHERE_ENABLED);
mPreviewViewSphereSize = lcGetProfileInt(LC_PROFILE_PREVIEW_VIEW_SPHERE_SIZE);
mPreviewViewSphereLocation = static_cast<lcViewSphereLocation>(lcGetProfileInt(LC_PROFILE_PREVIEW_VIEW_SPHERE_LOCATION));
mPreviewEnabled = lcGetProfileInt(LC_PROFILE_PREVIEW_ENABLED);
mPreviewSize = lcGetProfileInt(LC_PROFILE_PREVIEW_SIZE);
mPreviewLocation = static_cast<lcPreviewLocation>(lcGetProfileInt(LC_PROFILE_PREVIEW_LOCATION));
mPreviewPosition = static_cast<lcPreviewPosition>(lcGetProfileInt(LC_PROFILE_PREVIEW_POSITION));
mDrawPreviewAxis = lcGetProfileInt(LC_PROFILE_PREVIEW_DRAW_AXES);
mDrawPreviewViewSphere = lcGetProfileInt(LC_PROFILE_PREVIEW_DRAW_VIEW_SPHERE);
}
void lcPreferences::SaveDefaults()
@ -76,6 +88,17 @@ void lcPreferences::SaveDefaults()
lcSetProfileInt(LC_PROFILE_AUTOLOAD_MOSTRECENT, mAutoLoadMostRecent);
lcSetProfileInt(LC_PROFILE_RESTORE_TAB_LAYOUT, mRestoreTabLayout);
lcSetProfileInt(LC_PROFILE_COLOR_THEME, static_cast<int>(mColorTheme));
lcSetProfileInt(LC_PROFILE_PREVIEW_ACTIVE_COLOR, mPreviewActiveColor);
lcSetProfileInt(LC_PROFILE_PREVIEW_ENABLED, mPreviewViewSphereEnabled);
lcSetProfileInt(LC_PROFILE_PREVIEW_VIEW_SPHERE_SIZE, mPreviewViewSphereSize);
lcSetProfileInt(LC_PROFILE_PREVIEW_VIEW_SPHERE_LOCATION, static_cast<int>(mPreviewViewSphereLocation));
lcSetProfileInt(LC_PROFILE_PREVIEW_ENABLED, mPreviewEnabled);
lcSetProfileInt(LC_PROFILE_PREVIEW_SIZE, mPreviewSize);
lcSetProfileInt(LC_PROFILE_PREVIEW_LOCATION, static_cast<int>(mPreviewLocation));
lcSetProfileInt(LC_PROFILE_PREVIEW_POSITION, static_cast<int>(mPreviewPosition));
lcSetProfileInt(LC_PROFILE_PREVIEW_DRAW_AXES, mDrawPreviewAxis);
lcSetProfileInt(LC_PROFILE_PREVIEW_DRAW_VIEW_SPHERE, mDrawPreviewViewSphere);
}
void lcPreferences::SetInterfaceColors(lcColorTheme ColorTheme)
@ -220,6 +243,9 @@ void lcApplication::SetProject(Project* Project)
gMainWindow->RemoveAllModelTabs();
if (gMainWindow->GetPreviewWidget())
gMainWindow->GetPreviewWidget()->ClearPreview();
delete mProject;
mProject = Project;
@ -779,6 +805,8 @@ void lcApplication::ShowPreferencesDialog()
Options.MouseShortcutsModified = false;
Options.MouseShortcutsDefault = false;
lcPreviewPosition PreviewDockable = Options.Preferences.mPreviewPosition;
lcQPreferencesDialog Dialog(gMainWindow, &Options);
if (Dialog.exec() != QDialog::Accepted)
return;
@ -805,6 +833,11 @@ void lcApplication::ShowPreferencesDialog()
lcSetProfileInt(LC_PROFILE_ANTIALIASING_SAMPLES, Options.AASamples);
lcSetProfileInt(LC_PROFILE_STUD_LOGO, Options.StudLogo);
lcPreviewPosition Dockable = Options.Preferences.mPreviewPosition;
if (PreviewDockable != Dockable)
gMainWindow->TogglePreviewWidget(
Dockable == lcPreviewPosition::Dockable);
if (LanguageChanged || LibraryChanged || ColorsChanged || AAChanged)
QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("Some changes will only take effect the next time you start LeoCAD."));

View file

@ -21,6 +21,21 @@ enum class lcViewSphereLocation
BottomRight
};
enum class lcPreviewLocation
{
TopLeft,
TopRight,
BottomLeft,
BottomRight
};
enum class lcPreviewPosition
{
Dockable,
Floating,
Viewport // not implemented
};
enum class lcColorTheme
{
Dark,
@ -63,6 +78,17 @@ public:
bool mAutoLoadMostRecent;
bool mRestoreTabLayout;
lcColorTheme mColorTheme;
int mPreviewEnabled;
quint32 mPreviewActiveColor;
int mPreviewViewSphereEnabled;
int mPreviewViewSphereSize;
lcViewSphereLocation mPreviewViewSphereLocation;
lcPreviewLocation mPreviewLocation;
lcPreviewPosition mPreviewPosition;
int mPreviewSize;
int mDrawPreviewAxis;
int mDrawPreviewViewSphere;
};
class lcApplication : public QApplication
@ -112,4 +138,3 @@ inline lcPreferences& lcGetPreferences()
{
return gApplication->mPreferences;
}

View file

@ -24,6 +24,8 @@
#include "lc_library.h"
#include "lc_colors.h"
#include "lc_previewwidget.h"
#if LC_ENABLE_GAMEPAD
#include <QtGamepad/QGamepad>
#endif
@ -105,6 +107,7 @@ lcMainWindow::lcMainWindow()
mCurrentPieceInfo = nullptr;
mSelectionMode = lcSelectionMode::Single;
mModelTabWidget = nullptr;
mPreviewToolBar = nullptr;
memset(&mSearchOptions, 0, sizeof(mSearchOptions));
@ -163,8 +166,8 @@ void lcMainWindow::CreateWidgets()
connect(mModelTabWidget->tabBar(), SIGNAL(tabCloseRequested(int)), this, SLOT(ModelTabClosed(int)));
connect(mModelTabWidget->tabBar(), SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(ModelTabContextMenuRequested(const QPoint&)));
#else
mModelTabWidget->setMovable(true);
mModelTabWidget->setTabsClosable(true);
mModelTabWidget->setMovable(true);
mModelTabWidget->setTabsClosable(true);
connect(mModelTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(ModelTabClosed(int)));
#endif
setCentralWidget(mModelTabWidget);
@ -746,11 +749,71 @@ void lcMainWindow::CreateToolBars()
mTimelineToolBar->setWidget(mTimelineWidget);
addDockWidget(Qt::RightDockWidgetArea, mTimelineToolBar);
// Preview
const lcPreferences& Preferences = lcGetPreferences();
if (Preferences.mPreviewPosition == lcPreviewPosition::Dockable)
CreatePreviewWidget();
tabifyDockWidget(mPartsToolBar, mPropertiesToolBar);
tabifyDockWidget(mPropertiesToolBar, mTimelineToolBar);
connect(mPropertiesToolBar, SIGNAL (topLevelChanged(bool)), this, SLOT (EnableWindowFlags(bool)));
connect(mTimelineToolBar, SIGNAL (topLevelChanged(bool)), this, SLOT (EnableWindowFlags(bool)));
connect(mPartsToolBar, SIGNAL (topLevelChanged(bool)), this, SLOT (EnableWindowFlags(bool)));
connect(mColorsToolBar, SIGNAL (topLevelChanged(bool)), this, SLOT (EnableWindowFlags(bool)));
mPartsToolBar->raise();
}
void lcMainWindow::PreviewPiece(const QString &PartType, int ColorCode)
{
if (mPreviewWidget) {
if (!mPreviewWidget->SetCurrentPiece(PartType, ColorCode))
QMessageBox::critical(gMainWindow, tr("Error"), tr("Part preview for % failed.").arg(PartType));
}
}
void lcMainWindow::CreatePreviewWidget()
{
mPreviewWidget = new lcPreviewDockWidget();
mPreviewToolBar = new QDockWidget(tr("Preview"), this);
mPreviewToolBar->setWindowTitle(trUtf8("Preview"));
mPreviewToolBar->setObjectName("PreviewToolBarw");
mPreviewToolBar->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
mPreviewToolBar->setWidget(mPreviewWidget);
addDockWidget(Qt::RightDockWidgetArea, mPreviewToolBar);
tabifyDockWidget(mTimelineToolBar, mPreviewToolBar);
connect(mPreviewToolBar, SIGNAL (topLevelChanged(bool)), this, SLOT (EnableWindowFlags(bool)));
}
void lcMainWindow::TogglePreviewWidget(bool visible)
{
if (mPreviewToolBar) {
if (visible)
mPreviewToolBar->show();
else
mPreviewToolBar->hide();
} else if (visible) {
CreatePreviewWidget();
}
}
void lcMainWindow::EnableWindowFlags(bool Detached)
{
if (Detached) {
QDockWidget *DockWidget = qobject_cast<QDockWidget *>(sender());
DockWidget->setWindowFlags(Qt::CustomizeWindowHint |
Qt::Window |
Qt::WindowMinimizeButtonHint |
Qt::WindowMaximizeButtonHint |
Qt::WindowCloseButtonHint);
DockWidget->show();
}
}
class lcElidedLabel : public QFrame
{
public:

View file

@ -7,6 +7,7 @@
class View;
class lcPartSelectionWidget;
class lcPreviewDockWidget;
class PiecePreview;
class lcQGLWidget;
class lcQPartsTree;
@ -246,6 +247,11 @@ public:
return mPartSelectionWidget;
}
lcPreviewDockWidget* GetPreviewWidget() const
{
return mPreviewWidget;
}
QMenu* GetToolsMenu() const
{
return mToolsMenu;
@ -352,6 +358,8 @@ public:
public slots:
void ProjectFileChanged(const QString& Path);
void PreviewPiece(const QString &, int);
void TogglePreviewWidget(bool);
protected slots:
void UpdateDockWidgetActions();
@ -364,6 +372,7 @@ protected slots:
void ActionTriggered();
void ColorChanged(int ColorIndex);
void Print(QPrinter* Printer);
void EnableWindowFlags(bool);
protected:
void closeEvent(QCloseEvent *event) override;
@ -384,6 +393,7 @@ protected:
void ShowRenderDialog();
void ShowInstructionsDialog();
void ShowPrintDialog();
void CreatePreviewWidget();
bool OpenProjectFile(const QString& FileName);
@ -423,6 +433,7 @@ protected:
QToolBar* mStandardToolBar;
QToolBar* mToolsToolBar;
QToolBar* mTimeToolBar;
QDockWidget* mPreviewToolBar;
QDockWidget* mPartsToolBar;
QDockWidget* mColorsToolBar;
QDockWidget* mPropertiesToolBar;
@ -435,6 +446,7 @@ protected:
QLineEdit* mTransformXEdit;
QLineEdit* mTransformYEdit;
QLineEdit* mTransformZEdit;
lcPreviewDockWidget* mPreviewWidget;
lcElidedLabel* mStatusBarLabel;
QLabel* mStatusPositionLabel;

View file

@ -23,6 +23,7 @@
#include "lc_qpropertiesdialog.h"
#include "lc_qutils.h"
#include "lc_lxf.h"
#include "lc_previewwidget.h"
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#include <QtConcurrent>
#endif
@ -180,7 +181,8 @@ void lcModelProperties::ParseLDrawLine(QTextStream& Stream)
}
}
lcModel::lcModel(const QString& FileName)
lcModel::lcModel(const QString& FileName, bool Preview)
: mIsPreview(Preview)
{
mProperties.mModelName = FileName;
mProperties.mFileName = FileName;
@ -196,7 +198,7 @@ lcModel::~lcModel()
{
if (mPieceInfo)
{
if (gMainWindow && gMainWindow->GetCurrentPieceInfo() == mPieceInfo)
if (!mIsPreview && gMainWindow && gMainWindow->GetCurrentPieceInfo() == mPieceInfo)
gMainWindow->SetCurrentPieceInfo(nullptr);
if (mPieceInfo->GetModel() == this)
@ -264,7 +266,13 @@ void lcModel::DeleteModel()
lcReleaseTexture(mBackgroundTexture);
mBackgroundTexture = nullptr;
if (gMainWindow)
if (mIsPreview && gPreviewWidget) {
lcCamera* Camera = gPreviewWidget->GetCamera();
if (Camera && !Camera->IsSimple() && mCameras.FindIndex(Camera) != -1)
gPreviewWidget->SetCamera(Camera);
}
else if (gMainWindow)
{
const lcArray<View*>* Views = gMainWindow->GetViewsForModel(this);
@ -1819,6 +1827,10 @@ void lcModel::SubModelCompareBoundingBox(const lcMatrix44& WorldMatrix, lcVector
void lcModel::SaveCheckpoint(const QString& Description)
{
if (mIsPreview) {
return;
}
lcModelHistoryEntry* ModelHistoryEntry = new lcModelHistoryEntry();
ModelHistoryEntry->Description = Description;
@ -1840,6 +1852,10 @@ void lcModel::SaveCheckpoint(const QString& Description)
void lcModel::LoadCheckPoint(lcModelHistoryEntry* CheckPoint)
{
if (mIsPreview) {
return;
}
lcPiecesLibrary* Library = lcGetPiecesLibrary();
std::vector<PieceInfo*> LoadedInfos;
@ -2424,10 +2440,12 @@ void lcModel::DeleteSelectedObjects()
{
if (RemoveSelectedObjects())
{
gMainWindow->UpdateTimeline(false, false);
gMainWindow->UpdateSelectedObjects(true);
gMainWindow->UpdateAllViews();
SaveCheckpoint(tr("Deleting"));
if (!mIsPreview) {
gMainWindow->UpdateTimeline(false, false);
gMainWindow->UpdateSelectedObjects(true);
gMainWindow->UpdateAllViews();
SaveCheckpoint(tr("Deleting"));
}
}
}
@ -3861,8 +3879,10 @@ void lcModel::SelectAllPieces()
if (Piece->IsVisible(mCurrentStep))
Piece->SetSelected(true);
gMainWindow->UpdateSelectedObjects(true);
gMainWindow->UpdateAllViews();
if (!mIsPreview) {
gMainWindow->UpdateSelectedObjects(true);
gMainWindow->UpdateAllViews();
}
}
void lcModel::InvertSelection()
@ -4026,7 +4046,8 @@ void lcModel::FindPiece(bool FindFirst, bool SearchForward)
void lcModel::UndoAction()
{
if (mUndoHistory.size() < 2)
if (mIsPreview || mUndoHistory.size() < 2)
return;
lcModelHistoryEntry* Undo = mUndoHistory.front();
@ -4041,7 +4062,7 @@ void lcModel::UndoAction()
void lcModel::RedoAction()
{
if (mRedoHistory.empty())
if (mIsPreview || mRedoHistory.empty())
return;
lcModelHistoryEntry* Redo = mRedoHistory.front();
@ -4061,7 +4082,7 @@ void lcModel::BeginMouseTool()
void lcModel::EndMouseTool(lcTool Tool, bool Accept)
{
if (!Accept)
if (!Accept && !mIsPreview)
{
LoadCheckPoint(mUndoHistory[0]);
return;
@ -4078,7 +4099,8 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept)
break;
case LC_TOOL_CAMERA:
gMainWindow->UpdateCameraMenu();
if (!mIsPreview)
gMainWindow->UpdateCameraMenu();
SaveCheckpoint(tr("New Camera"));
break;
@ -4099,22 +4121,22 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept)
break;
case LC_TOOL_ZOOM:
if (!gMainWindow->GetActiveView()->mCamera->IsSimple())
if (!mIsPreview && !gMainWindow->GetActiveView()->mCamera->IsSimple())
SaveCheckpoint(tr("Zoom"));
break;
case LC_TOOL_PAN:
if (!gMainWindow->GetActiveView()->mCamera->IsSimple())
if (!mIsPreview && !gMainWindow->GetActiveView()->mCamera->IsSimple())
SaveCheckpoint(tr("Pan"));
break;
case LC_TOOL_ROTATE_VIEW:
if (!gMainWindow->GetActiveView()->mCamera->IsSimple())
if (!mIsPreview && !gMainWindow->GetActiveView()->mCamera->IsSimple())
SaveCheckpoint(tr("Orbit"));
break;
case LC_TOOL_ROLL:
if (!gMainWindow->GetActiveView()->mCamera->IsSimple())
if (!mIsPreview && !gMainWindow->GetActiveView()->mCamera->IsSimple())
SaveCheckpoint(tr("Roll"));
break;
@ -4308,7 +4330,8 @@ void lcModel::UpdatePanTool(lcCamera* Camera, const lcVector3& Distance)
{
Camera->Pan(Distance - mMouseToolDistance, mCurrentStep, gMainWindow->GetAddKeys());
mMouseToolDistance = Distance;
gMainWindow->UpdateAllViews();
if (!mIsPreview)
gMainWindow->UpdateAllViews();
}
void lcModel::UpdateOrbitTool(lcCamera* Camera, float MouseX, float MouseY)
@ -4318,7 +4341,8 @@ void lcModel::UpdateOrbitTool(lcCamera* Camera, float MouseX, float MouseY)
Camera->Orbit(MouseX - mMouseToolDistance.x, MouseY - mMouseToolDistance.y, Center, mCurrentStep, gMainWindow->GetAddKeys());
mMouseToolDistance.x = MouseX;
mMouseToolDistance.y = MouseY;
gMainWindow->UpdateAllViews();
if (!mIsPreview)
gMainWindow->UpdateAllViews();
}
void lcModel::UpdateRollTool(lcCamera* Camera, float Mouse)
@ -4384,10 +4408,12 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect)
lcVector3 Points[8];
lcGetBoxCorners(Min, Max, Points);
Camera->ZoomExtents(Aspect, Center, Points, 8, mCurrentStep, gMainWindow->GetAddKeys());
Camera->ZoomExtents(Aspect, Center, Points, 8, mCurrentStep, mIsPreview ? false : gMainWindow->GetAddKeys());
gMainWindow->UpdateSelectedObjects(false);
gMainWindow->UpdateAllViews();
if (!mIsPreview) {
gMainWindow->UpdateSelectedObjects(false);
gMainWindow->UpdateAllViews();
}
if (!Camera->IsSimple())
SaveCheckpoint(tr("Zoom"));
@ -4395,10 +4421,11 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect)
void lcModel::Zoom(lcCamera* Camera, float Amount)
{
Camera->Zoom(Amount, mCurrentStep, gMainWindow->GetAddKeys());
gMainWindow->UpdateSelectedObjects(false);
gMainWindow->UpdateAllViews();
Camera->Zoom(Amount, mCurrentStep, mIsPreview ? false : gMainWindow->GetAddKeys());
if (!mIsPreview) {
gMainWindow->UpdateSelectedObjects(false);
gMainWindow->UpdateAllViews();
}
if (!Camera->IsSimple())
SaveCheckpoint(tr("Zoom"));
}

View file

@ -103,7 +103,7 @@ struct lcModelHistoryEntry
class lcModel
{
public:
lcModel(const QString& FileName);
lcModel(const QString& FileName, bool Preview = false);
~lcModel();
lcModel(const lcModel&) = delete;
@ -116,6 +116,11 @@ public:
return mSavedHistory != mUndoHistory[0];
}
bool IsPreview()
{
return mIsPreview;
}
bool GetPieceWorldMatrix(lcPiece* Piece, lcMatrix44& ParentWorldMatrix) const;
bool IncludesModel(const lcModel* Model) const;
void CreatePieceInfo(Project* Project);
@ -234,7 +239,13 @@ public:
if (mUndoHistory.empty())
SaveCheckpoint(QString());
mSavedHistory = mUndoHistory[0];
if (!mIsPreview)
mSavedHistory = mUndoHistory[0];
}
void SetPreviewPiece(lcPiece* Piece)
{
AddPiece(Piece);
}
void Cut();
@ -379,6 +390,7 @@ protected:
lcModelProperties mProperties;
PieceInfo* mPieceInfo;
bool mIsPreview;
bool mActive;
lcStep mCurrentStep;
lcVector3 mMouseToolDistance;

View file

@ -11,6 +11,9 @@
#include "view.h"
#include "lc_glextensions.h"
#include "lc_qglwidget.h"
#include "lc_previewwidget.h"
Q_DECLARE_METATYPE(QList<int>)
void lcPartSelectionItemDelegate::paint(QPainter* Painter, const QStyleOptionViewItem& Option, const QModelIndex& Index) const
@ -412,7 +415,7 @@ void lcPartSelectionListModel::DrawPreview(int InfoIndex)
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
lcMatrix44 ProjectionMatrix, ViewMatrix;
Info->ZoomExtents(20.0f, Aspect, ProjectionMatrix, ViewMatrix);
@ -572,9 +575,9 @@ void lcPartSelectionListView::SetCategory(lcPartCategoryType Type, int Index)
case lcPartCategoryType::Category:
mListModel->SetCategory(Index);
break;
case lcPartCategoryType::Count:
break;
}
case lcPartCategoryType::Count:
break;
}
setCurrentIndex(mListModel->index(0, 0));
}
@ -680,6 +683,91 @@ void lcPartSelectionListView::startDrag(Qt::DropActions SupportedActions)
Drag->exec(Qt::CopyAction);
}
void lcPartSelectionListView::mouseDoubleClickEvent(QMouseEvent *event)
{
QAbstractItemView::mouseDoubleClickEvent(event);
if ( event->button() == Qt::LeftButton ) {
PreviewSelection(currentIndex().row());
}
}
void lcPartSelectionListView::PreviewSelection(int InfoIndex)
{
PieceInfo* Info = mListModel->GetPieceInfo(InfoIndex);
if (!Info)
return;
bool IsSubfile = Info->IsModel();
QString PartType = Info->mFileName;
quint32 ColorCode = IsSubfile ? 16 : lcGetColorCode(mListModel->GetColorIndex());
const lcPreferences& Preferences = lcGetPreferences();
if (Preferences.mPreviewPosition != lcPreviewPosition::Floating) {
emit gMainWindow->PreviewPiece(PartType, ColorCode);
return;
}
if (!Preferences.mPreviewEnabled)
return;
QString TypeLabel = IsSubfile ? "Submodel" : "Part";
QString WindowTitle = QString("%1 Preview").arg(TypeLabel);
lcPreviewWidget *Preview = new lcPreviewWidget();
lcQGLWidget *ViewWidget = new lcQGLWidget(nullptr, Preview, true/*isView*/, true/*isPreview*/);
if (Preview && ViewWidget) {
if (!Preview->SetCurrentPiece(PartType, ColorCode))
QMessageBox::critical(gMainWindow, tr("Error"), tr("Preview %1 failed.").arg(Info->mFileName));
ViewWidget->setWindowTitle(WindowTitle);
int Size[2] = { 300,200 };
if (Preferences.mPreviewSize == 400) {
Size[0] = 400; Size[1] = 300;
}
ViewWidget->preferredSize = QSize(Size[0], Size[1]);
float Scale = ViewWidget->deviceScale();
Preview->mWidth = ViewWidget->width() * Scale;
Preview->mHeight = ViewWidget->height() * Scale;
const QRect desktop = QApplication::desktop()->geometry();
QPoint pos;
switch (Preferences.mPreviewLocation)
{
case lcPreviewLocation::TopRight:
pos = mapToGlobal(rect().topRight());
break;
case lcPreviewLocation::TopLeft:
pos = mapToGlobal(rect().topLeft());
break;
case lcPreviewLocation::BottomRight:
pos = mapToGlobal(rect().bottomRight());
break;
default:
pos = mapToGlobal(rect().bottomLeft());
break;
}
if (pos.x() < desktop.left())
pos.setX(desktop.left());
if (pos.y() < desktop.top())
pos.setY(desktop.top());
if ((pos.x() + ViewWidget->width()) > desktop.width())
pos.setX(desktop.width() - ViewWidget->width());
if ((pos.y() + ViewWidget->height()) > desktop.bottom())
pos.setY(desktop.bottom() - ViewWidget->height());
ViewWidget->move(pos);
ViewWidget->setMinimumSize(100,100);
ViewWidget->show();
ViewWidget->setFocus();
} else {
QMessageBox::critical(gMainWindow, tr("Error"), tr("Preview %1 failed.").arg(Info->mFileName));
}
}
lcPartSelectionWidget::lcPartSelectionWidget(QWidget* Parent)
: QWidget(Parent), mFilterAction(nullptr)
{

View file

@ -88,6 +88,11 @@ public:
return mShowPartNames;
}
int GetColorIndex() const
{
return mColorIndex;
}
bool IsColorLocked() const
{
return mColorLocked;
@ -182,6 +187,8 @@ public slots:
protected:
void SetIconSize(int Size);
void PreviewSelection(int InfoIndex);
void mouseDoubleClickEvent(QMouseEvent *event) override;
lcPartSelectionListModel* mListModel;
lcPartSelectionWidget* mPartSelectionWidget;

637
common/lc_previewwidget.cpp Normal file
View file

@ -0,0 +1,637 @@
#include "QMessageBox"
#include "lc_global.h"
#include "lc_previewwidget.h"
#include "pieceinf.h"
#include "piece.h"
#include "project.h"
#include "lc_model.h"
#include "camera.h"
#include "texfont.h"
#include "lc_library.h"
#include "lc_qglwidget.h"
lcPreviewWidget* gPreviewWidget;
lcPreviewDockWidget::lcPreviewDockWidget(QMainWindow *parent)
:QMainWindow(parent)
{
Preview = new lcPreviewWidget();
ViewWidget = new lcQGLWidget(nullptr, Preview, true/*IsView*/, true/*IsPreview*/);
setCentralWidget(ViewWidget);
setMinimumSize(200, 200);
ToolBar = addToolBar(tr("PreviewDescription"));
ToolBar->setObjectName("PreviewDescription");
ToolBar->setMovable(false);
Label = new QLabel("");
ToolBar->addWidget(Label);
}
bool lcPreviewDockWidget::SetCurrentPiece(const QString &PartType, int ColorCode)
{
Label->setText("Loading...");
if (Preview->SetCurrentPiece(PartType, ColorCode)) {
Label->setText(Preview->GetDescription());
return true;
}
return false;
}
void lcPreviewDockWidget::ClearPreview()
{
Preview->ClearPreview();
Label->setText("");
}
lcPreviewWidget::lcPreviewWidget()
: mLoader(new Project(true/*IsPreview*/)),
mViewSphere(this/*Preview*/),
mIsPart(false)
{
mTool = LC_TOOL_SELECT;
mTrackTool = LC_TRACKTOOL_NONE;
mTrackButton = lcTrackButton::None;
mLoader->SetActiveModel(0);
mModel = mLoader->GetActiveModel();
mCamera = nullptr;
SetDefaultCamera();
}
lcPreviewWidget::~lcPreviewWidget()
{
if (mCamera && mCamera->IsSimple())
delete mCamera;
if (mIsPart) {
lcPiecesLibrary* Library = lcGetPiecesLibrary();
for (lcPiece* Piece : mModel->GetPieces())
{
PieceInfo *Info = Piece->mPieceInfo;
Library->ReleasePieceInfo(Info);
}
}
}
bool lcPreviewWidget::SetCurrentPiece(const QString &PartType, int ColorCode)
{
lcPiecesLibrary *Library = lcGetPiecesLibrary();
PieceInfo* Info = Library->FindPiece(PartType.toLatin1().constData(), nullptr, false, false);
if (Info) {
mIsPart = true;
mDescription = Info->m_strDescription;
lcModel* ActiveModel = GetActiveModel();
ActiveModel->SelectAllPieces();
ActiveModel->DeleteSelectedObjects();
Library->LoadPieceInfo(Info, false, true);
Library->WaitForLoadQueue();
float* Matrix = lcMatrix44Identity();;
lcMatrix44 Transform(lcVector4( Matrix[0], Matrix[2], -Matrix[1], 0.0f), lcVector4(Matrix[8], Matrix[10], -Matrix[9], 0.0f),
lcVector4(-Matrix[4], -Matrix[6], Matrix[5], 0.0f), lcVector4(Matrix[12], Matrix[14], -Matrix[13], 1.0f));
int CurrentStep = 1;
lcPiece* Piece = new lcPiece(nullptr);
Piece->SetPieceInfo(Info, PartType, false);
Piece->Initialize(Transform, CurrentStep);
Piece->SetColorCode(ColorCode);
ActiveModel->SetPreviewPiece(Piece);
Piece = nullptr;
} else {
QString ModelPath = QString("%1/%2")
.arg(QDir::currentPath())
.arg(PartType);
if (!mLoader->Load(ModelPath)) {
QMessageBox::critical(nullptr, QMessageBox::tr("Error"), QMessageBox::tr("Failed to load '%1'.").arg(ModelPath));
return false;
}
mLoader->SetActiveModel(0);
lcGetPiecesLibrary()->RemoveTemporaryPieces();
mModel = mLoader->GetActiveModel();
if (!mModel->GetProperties().mDescription.isEmpty())
mDescription = mModel->GetProperties().mDescription;
else
mDescription = PartType;
}
ZoomExtents();
return true;
}
void lcPreviewWidget::ClearPreview()
{
mLoader = new Project(true/*IsPreview*/);
mLoader->SetActiveModel(0);
mModel = mLoader->GetActiveModel();
lcGetPiecesLibrary()->UnloadUnusedParts();
Redraw();
}
void lcPreviewWidget::SetDefaultCamera()
{
if (!mCamera || !mCamera->IsSimple())
mCamera = new lcCamera(true);
mCamera->SetViewpoint(LC_VIEWPOINT_HOME);
}
void lcPreviewWidget::SetCamera(lcCamera* Camera) // called by lcModel::DeleteModel()
{
if (!mCamera || !mCamera->IsSimple())
mCamera = new lcCamera(true);
mCamera->CopyPosition(Camera);
}
lcModel* lcPreviewWidget::GetActiveModel() const
{
return mModel;
}
void lcPreviewWidget::ZoomExtents()
{
lcModel* ActiveModel = GetActiveModel();
if (ActiveModel) {
ActiveModel->ZoomExtents(mCamera, float(mWidth) / float(mHeight));
Redraw();
}
}
lcMatrix44 lcPreviewWidget::GetProjectionMatrix() const
{
float AspectRatio = (float)mWidth / (float)mHeight;
if (mCamera->IsOrtho())
{
float OrthoHeight = mCamera->GetOrthoHeight() / 2.0f;
float OrthoWidth = OrthoHeight * AspectRatio;
return lcMatrix44Ortho(-OrthoWidth, OrthoWidth, -OrthoHeight, OrthoHeight, mCamera->m_zNear, mCamera->m_zFar * 4);
}
else
return lcMatrix44Perspective(mCamera->m_fovy, AspectRatio, mCamera->m_zNear, mCamera->m_zFar);
}
void lcPreviewWidget::StartOrbitTracking() // called by viewSphere
{
mTrackTool = LC_TRACKTOOL_ORBIT_XY;
OnUpdateCursor();
OnButtonDown(lcTrackButton::Left);
}
void lcPreviewWidget::SetViewpoint(const lcVector3& Position)
{
if (!mCamera || !mCamera->IsSimple())
{
lcCamera* OldCamera = mCamera;
mCamera = new lcCamera(true);
if (OldCamera)
mCamera->CopySettings(OldCamera);
}
mCamera->SetViewpoint(Position);
Redraw();
}
void lcPreviewWidget::DrawViewport()
{
mContext->SetWorldMatrix(lcMatrix44Identity());
mContext->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f));
mContext->SetDepthWrite(false);
glDisable(GL_DEPTH_TEST);
if (true/*we have an active view*/)
{
mContext->SetMaterial(lcMaterialType::UnlitColor);
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mPreviewActiveColor));
float Verts[8] = { 0.0f, 0.0f, mWidth - 1.0f, 0.0f, mWidth - 1.0f, mHeight - 1.0f, 0.0f, mHeight - 1.0f };
mContext->SetVertexBufferPointer(Verts);
mContext->SetVertexFormatPosition(2);
mContext->DrawPrimitives(GL_LINE_LOOP, 0, 4);
}
mContext->SetDepthWrite(true);
glEnable(GL_DEPTH_TEST);
}
void lcPreviewWidget::DrawAxes()
{
// glClear(GL_DEPTH_BUFFER_BIT);
const float Verts[28 * 3] =
{
0.00f, 0.00f, 0.00f, 20.00f, 0.00f, 0.00f, 12.00f, 3.00f, 0.00f, 12.00f, 2.12f, 2.12f,
12.00f, 0.00f, 3.00f, 12.00f, -2.12f, 2.12f, 12.00f, -3.00f, 0.00f, 12.00f, -2.12f, -2.12f,
12.00f, 0.00f, -3.00f, 12.00f, 2.12f, -2.12f, 0.00f, 20.00f, 0.00f, 3.00f, 12.00f, 0.00f,
2.12f, 12.00f, 2.12f, 0.00f, 12.00f, 3.00f, -2.12f, 12.00f, 2.12f, -3.00f, 12.00f, 0.00f,
-2.12f, 12.00f, -2.12f, 0.00f, 12.00f, -3.00f, 2.12f, 12.00f, -2.12f, 0.00f, 0.00f, 20.00f,
0.00f, 3.00f, 12.00f, 2.12f, 2.12f, 12.00f, 3.00f, 0.00f, 12.00f, 2.12f, -2.12f, 12.00f,
0.00f, -3.00f, 12.00f, -2.12f, -2.12f, 12.00f, -3.00f, 0.00f, 12.00f, -2.12f, 2.12f, 12.00f,
};
const GLushort Indices[78] =
{
0, 1, 0, 10, 0, 19,
1, 2, 3, 1, 3, 4, 1, 4, 5, 1, 5, 6, 1, 6, 7, 1, 7, 8, 1, 8, 9, 1, 9, 2,
10, 11, 12, 10, 12, 13, 10, 13, 14, 10, 14, 15, 10, 15, 16, 10, 16, 17, 10, 17, 18, 10, 18, 11,
19, 20, 21, 19, 21, 22, 19, 22, 23, 19, 23, 24, 19, 24, 25, 19, 25, 26, 19, 26, 27, 19, 27, 20
};
lcMatrix44 TranslationMatrix = lcMatrix44Translation(lcVector3(30.375f, 30.375f, 0.0f));
lcMatrix44 WorldViewMatrix = mCamera->mWorldView;
WorldViewMatrix.SetTranslation(lcVector3(0, 0, 0));
mContext->SetMaterial(lcMaterialType::UnlitColor);
mContext->SetWorldMatrix(lcMatrix44Identity());
mContext->SetViewMatrix(lcMul(WorldViewMatrix, TranslationMatrix));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0, mWidth, 0, mHeight, -50, 50));
mContext->SetVertexBufferPointer(Verts);
mContext->SetVertexFormatPosition(3);
mContext->SetIndexBufferPointer(Indices);
mContext->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_LINES, 6, GL_UNSIGNED_SHORT, 0);
mContext->SetColor(0.8f, 0.0f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, 6 * 2);
mContext->SetColor(0.0f, 0.8f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, (6 + 24) * 2);
mContext->SetColor(0.0f, 0.0f, 0.8f, 1.0f);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, (6 + 48) * 2);
mContext->SetMaterial(lcMaterialType::UnlitTextureModulate);
mContext->SetViewMatrix(TranslationMatrix);
mContext->BindTexture2D(gTexFont.GetTexture());
glEnable(GL_BLEND);
float TextBuffer[6 * 5 * 3];
/*** Native viewer camera globe mod, switch Y and Z axis with -Y(LC -Z) in the up direction ***/
lcVector3 PosX = lcMul30(lcVector3(25.0f, 0.0f, 0.0f), WorldViewMatrix);
gTexFont.GetGlyphTriangles(PosX.x, PosX.y, PosX.z, 'X', TextBuffer);
lcVector3 PosY = lcMul30(lcVector3(0.0f, 25.0f, 0.0f), WorldViewMatrix);
gTexFont.GetGlyphTriangles(PosY.x, PosY.y, PosY.z, 'Z', TextBuffer + 5 * 6);
lcVector3 PosZ = lcMul30(lcVector3(0.0f, 0.0f, 25.0f), WorldViewMatrix);
gTexFont.GetGlyphTriangles(PosZ.x, PosZ.y, PosZ.z, 'Y', TextBuffer + 5 * 6 * 2);
/*** Camera globe mod end ***/
mContext->SetVertexBufferPointer(TextBuffer);
mContext->SetVertexFormat(0, 3, 0, 2, 0, false);
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mAxesColor));
mContext->DrawPrimitives(GL_TRIANGLES, 0, 6 * 3);
glDisable(GL_BLEND);
}
lcTool lcPreviewWidget::GetCurrentTool() const
{
const lcTool ToolFromTrackTool[] =
{
LC_TOOL_SELECT, // LC_TRACKTOOL_NONE
LC_TOOL_PAN, // LC_TRACKTOOL_PAN
LC_TOOL_ROTATE_VIEW, // LC_TRACKTOOL_ORBIT_XY
};
return ToolFromTrackTool[mTrackTool];
}
void lcPreviewWidget::StartTracking(lcTrackButton TrackButton)
{
mTrackButton = TrackButton;
mTrackUpdated = false;
mMouseDownX = mInputState.x;
mMouseDownY = mInputState.y;
lcTool Tool = GetCurrentTool(); // Either LC_TRACKTOOL_NONE (LC_TOOL_SELECT) or LC_TRACKTOOL_ORBIT_XY (LC_TOOL_ROTATE_VIEW)
lcModel* ActiveModel = GetActiveModel();
switch (Tool)
{
case LC_TOOL_SELECT:
break;
case LC_TOOL_PAN:
case LC_TOOL_ROTATE_VIEW:
ActiveModel->BeginMouseTool();
break;
case LC_NUM_TOOLS:
default:
break;
}
OnUpdateCursor();
}
void lcPreviewWidget::StopTracking(bool Accept)
{
if (mTrackButton == lcTrackButton::None)
return;
lcTool Tool = GetCurrentTool(); // Either LC_TRACKTOOL_NONE (LC_TOOL_SELECT) or LC_TRACKTOOL_ORBIT_XY (LC_TOOL_ROTATE_VIEW)
lcModel* ActiveModel = GetActiveModel();
switch (Tool)
{
case LC_TOOL_SELECT:
break;
case LC_TOOL_PAN:
case LC_TOOL_ROTATE_VIEW:
ActiveModel->EndMouseTool(Tool, Accept);
break;
case LC_NUM_TOOLS:
default:
break;
}
mTrackButton = lcTrackButton::None;
mTrackTool = LC_TRACKTOOL_NONE;
OnUpdateCursor();
}
void lcPreviewWidget::OnButtonDown(lcTrackButton TrackButton)
{
switch (mTrackTool)
{
case LC_TRACKTOOL_NONE:
break;
case LC_TRACKTOOL_PAN:
StartTracking(TrackButton);
break;
case LC_TRACKTOOL_ORBIT_XY:
StartTracking(TrackButton);
break;
case LC_TRACKTOOL_COUNT:
break;
}
}
lcCursor lcPreviewWidget::GetCursor() const
{
const lcCursor CursorFromTrackTool[] =
{
lcCursor::Select, // LC_TRACKTOOL_NONE
lcCursor::Pan, // LC_TRACKTOOL_PAN
lcCursor::RotateView, // LC_TRACKTOOL_ORBIT_XY
};
static_assert(LC_ARRAY_COUNT(CursorFromTrackTool) == LC_TRACKTOOL_COUNT, "Tracktool array size mismatch.");
if (mTrackTool >= 0 && mTrackTool < LC_ARRAY_COUNT(CursorFromTrackTool))
return CursorFromTrackTool[mTrackTool];
return lcCursor::Select;
}
void lcPreviewWidget::OnInitialUpdate()
{
MakeCurrent();
mContext->SetDefaultState();
}
void lcPreviewWidget::OnDraw()
{
if (!mModel)
return;
lcPreferences& Preferences = lcGetPreferences();
const bool DrawInterface = mWidget != nullptr;
mScene.SetAllowLOD(Preferences.mAllowLOD && mWidget != nullptr);
mScene.SetLODDistance(Preferences.mMeshLODDistance);
mScene.Begin(mCamera->mWorldView);
mScene.SetDrawInterface(DrawInterface);
mModel->GetScene(mScene, mCamera, false /*HighlightNewParts*/, false/*mFadeSteps*/);
mScene.End();
mContext->SetDefaultState();
mContext->SetViewport(0, 0, mWidth, mHeight);
mModel->DrawBackground(this);
mContext->SetProjectionMatrix(GetProjectionMatrix());
mContext->SetLineWidth(Preferences.mLineWidth);
mScene.Draw(mContext);
if (DrawInterface)
{
mContext->SetLineWidth(1.0f);
if (Preferences.mDrawPreviewAxis)
DrawAxes();
if (Preferences.mDrawPreviewViewSphere)
mViewSphere.Draw();
DrawViewport();
}
mContext->ClearResources();
}
void lcPreviewWidget::OnUpdateCursor()
{
SetCursor(GetCursor());
}
void lcPreviewWidget::OnLeftButtonDown()
{
if (mTrackButton != lcTrackButton::None)
{
StopTracking(false);
return;
}
if (mViewSphere.OnLeftButtonDown())
return;
lcTrackTool OverrideTool = LC_TRACKTOOL_ORBIT_XY;
if (OverrideTool != LC_TRACKTOOL_NONE)
{
mTrackTool = OverrideTool;
OnUpdateCursor();
}
OnButtonDown(lcTrackButton::Left);
}
void lcPreviewWidget::OnLeftButtonUp()
{
StopTracking(mTrackButton == lcTrackButton::Left);
if (mViewSphere.OnLeftButtonUp()) {
ZoomExtents();
return;
}
}
void lcPreviewWidget::OnMiddleButtonDown()
{
if (mTrackButton != lcTrackButton::None)
{
StopTracking(false);
return;
}
#if (QT_VERSION >= QT_VERSION_CHECK(4, 7, 0))
lcTrackTool OverrideTool = LC_TRACKTOOL_NONE;
if (OverrideTool != LC_TRACKTOOL_NONE)
{
mTrackTool = OverrideTool;
OnUpdateCursor();
}
#endif
OnButtonDown(lcTrackButton::Middle);
}
void lcPreviewWidget::OnMiddleButtonUp()
{
StopTracking(mTrackButton == lcTrackButton::Middle);
}
void lcPreviewWidget::OnLeftButtonDoubleClick()
{
ZoomExtents();
Redraw();
}
void lcPreviewWidget::OnRightButtonDown()
{
if (mTrackButton != lcTrackButton::None)
{
StopTracking(false);
return;
}
lcTrackTool OverrideTool = LC_TRACKTOOL_PAN;
if (OverrideTool != LC_TRACKTOOL_NONE)
{
mTrackTool = OverrideTool;
OnUpdateCursor();
}
OnButtonDown(lcTrackButton::Middle);
}
void lcPreviewWidget::OnRightButtonUp()
{
if (mTrackButton != lcTrackButton::None)
StopTracking(mTrackButton == lcTrackButton::Right);
}
void lcPreviewWidget::OnMouseMove()
{
lcModel* ActiveModel = GetActiveModel();
if (!ActiveModel)
return;
if (mTrackButton == lcTrackButton::None)
{
if (mViewSphere.OnMouseMove())
{
lcTrackTool NewTrackTool = mViewSphere.IsDragging() ? LC_TRACKTOOL_ORBIT_XY : LC_TRACKTOOL_NONE;
if (NewTrackTool != mTrackTool)
{
mTrackTool = NewTrackTool;
OnUpdateCursor();
}
return;
}
return;
}
mTrackUpdated = true;
const float MouseSensitivity = 0.5f / (21.0f - lcGetPreferences().mMouseSensitivity);
switch (mTrackTool)
{
case LC_TRACKTOOL_NONE:
break;
case LC_TRACKTOOL_PAN:
{
lcVector3 Points[4] =
{
lcVector3((float)mInputState.x, (float)mInputState.y, 0.0f),
lcVector3((float)mInputState.x, (float)mInputState.y, 1.0f),
lcVector3(mMouseDownX, mMouseDownY, 0.0f),
lcVector3(mMouseDownX, mMouseDownY, 1.0f)
};
UnprojectPoints(Points, 4);
const lcVector3& CurrentStart = Points[0];
const lcVector3& CurrentEnd = Points[1];
const lcVector3& MouseDownStart = Points[2];
const lcVector3& MouseDownEnd = Points[3];
lcVector3 Center = ActiveModel->GetSelectionOrModelCenter();
lcVector3 PlaneNormal(mCamera->mPosition - mCamera->mTargetPosition);
lcVector4 Plane(PlaneNormal, -lcDot(PlaneNormal, Center));
lcVector3 Intersection, MoveStart;
if (!lcLineSegmentPlaneIntersection(&Intersection, CurrentStart, CurrentEnd, Plane) || !lcLineSegmentPlaneIntersection(&MoveStart, MouseDownStart, MouseDownEnd, Plane))
{
Center = MouseDownStart + lcNormalize(MouseDownEnd - MouseDownStart) * 10.0f;
Plane = lcVector4(PlaneNormal, -lcDot(PlaneNormal, Center));
if (!lcLineSegmentPlaneIntersection(&Intersection, CurrentStart, CurrentEnd, Plane) || !lcLineSegmentPlaneIntersection(&MoveStart, MouseDownStart, MouseDownEnd, Plane))
break;
}
ActiveModel->UpdatePanTool(mCamera, MoveStart - Intersection);
Redraw();
}
break;
case LC_TRACKTOOL_ORBIT_XY:
ActiveModel->UpdateOrbitTool(mCamera, 0.1f * MouseSensitivity * (mInputState.x - mMouseDownX), 0.1f * MouseSensitivity * (mInputState.y - mMouseDownY));
Redraw();
break;
case LC_TRACKTOOL_COUNT:
break;
}
}
void lcPreviewWidget::OnMouseWheel(float Direction)
{
mModel->Zoom(mCamera, (int)(((mInputState.Modifiers & Qt::ControlModifier) ? 100 : 10) * Direction));
Redraw();
}

145
common/lc_previewwidget.h Normal file
View file

@ -0,0 +1,145 @@
#ifndef PREVIEWWIDGET_H
#define PREVIEWWIDGET_H
#include <QMainWindow>
#include <QString>
#include "lc_global.h"
#include "lc_glwidget.h"
#include "lc_scene.h"
#include "lc_viewsphere.h"
#include "lc_commands.h"
#include "lc_application.h"
#include "camera.h"
class QLabel;
class Project;
class lcModel;
class lcPiece;
class lcQGLWidget;
class lcPreviewDockWidget : public QMainWindow
{
Q_OBJECT
public:
explicit lcPreviewDockWidget(QMainWindow *parent = nullptr);
bool SetCurrentPiece(const QString &PartType, int ColorCode);
void ClearPreview();
protected:
QToolBar *ToolBar;
QLabel *Label;
lcPreviewWidget *Preview;
lcQGLWidget *ViewWidget;
};
class lcPreviewWidget : public lcGLWidget
{
public:
enum class lcTrackButton
{
None,
Left,
Middle,
Right
};
enum lcTrackTool
{
LC_TRACKTOOL_NONE,
LC_TRACKTOOL_PAN,
LC_TRACKTOOL_ORBIT_XY,
LC_TRACKTOOL_COUNT
};
lcPreviewWidget();
~lcPreviewWidget();
lcTool GetTool() const
{
return mTool;
}
lcCamera* GetCamera() const
{
return mCamera;
}
QString GetDescription() const
{
return mDescription;
}
lcVector3 UnprojectPoint(const lcVector3& Point) const
{
int Viewport[4] = { 0, 0, mWidth, mHeight };
return lcUnprojectPoint(Point, mCamera->mWorldView, GetProjectionMatrix(), Viewport);
}
void UnprojectPoints(lcVector3* Points, int NumPoints) const
{
int Viewport[4] = { 0, 0, mWidth, mHeight };
lcUnprojectPoints(Points, NumPoints, mCamera->mWorldView, GetProjectionMatrix(), Viewport);
}
void ClearPreview();
bool SetCurrentPiece(const QString& PartType, int ColorCode);
lcMatrix44 GetProjectionMatrix() const;
lcModel* GetActiveModel() const;
lcCursor GetCursor() const;
void SetCamera(lcCamera* Camera);
void SetDefaultCamera();
void ZoomExtents();
// exclusively called from viewSphere
void SetViewpoint(const lcVector3& Position);
void StartOrbitTracking();
bool IsTracking() const
{
return mTrackButton != lcTrackButton::None;
}
void OnInitialUpdate() override;
void OnDraw() override;
void OnUpdateCursor() override;
void OnLeftButtonDown() override;
void OnLeftButtonUp() override;
void OnLeftButtonDoubleClick() override;
void OnMiddleButtonDown() override;
void OnMiddleButtonUp() override;
void OnRightButtonDown() override;
void OnRightButtonUp() override;
void OnMouseMove() override;
void OnMouseWheel(float Direction) override;
protected:
void DrawAxes();
void DrawViewport();
lcTool GetCurrentTool() const;
void StartTracking(lcTrackButton TrackButton);
void StopTracking(bool Accept);
void OnButtonDown(lcTrackButton TrackButton);
Project* mLoader;
lcModel* mModel;
lcCamera* mCamera;
lcViewSphere mViewSphere;
lcScene mScene;
lcTool mTool;
lcTrackButton mTrackButton;
lcTrackTool mTrackTool;
QString mDescription;
bool mIsPart;
bool mTrackUpdated;
int mMouseDownX;
int mMouseDownY;
};
extern class lcPreviewWidget* gPreviewWidget;
#endif // PREVIEWWIDGET_H

View file

@ -129,7 +129,18 @@ static lcProfileEntry gProfileEntries[LC_NUM_PROFILE_KEYS] =
lcProfileEntry("POVRay", "Path", "/usr/bin/povray"), // LC_PROFILE_POVRAY_PATH
lcProfileEntry("POVRay", "LGEOPath", ""), // LC_PROFILE_POVRAY_LGEO_PATH
lcProfileEntry("POVRay", "Width", 1280), // LC_PROFILE_POVRAY_WIDTH
lcProfileEntry("POVRay", "Height", 720) // LC_PROFILE_POVRAY_HEIGHT
lcProfileEntry("POVRay", "Height", 720), // LC_PROFILE_POVRAY_HEIGHT
lcProfileEntry("Settings", "PreviewActiveColor", LC_RGBA(69, 69, 69, 255)), // LC_PROFILE_PREVIEW_ACTIVE_COLOR
lcProfileEntry("Settgins", "PreviewViewSphereEnabled", 1), // LC_PROFILE_PREVIEW_VIEW_SPHERE_ENABLED
lcProfileEntry("Settings", "PreviewViewSphereSize", 75), // LC_PROFILE_PREVIEW_VIEW_SPHERE_SIZE
lcProfileEntry("Settings", "PreviewViewSphereLocation", (int)lcViewSphereLocation::TopRight), // LC_PROFILE_PREVIEW_VIEW_SPHERE_LOCATION
lcProfileEntry("Settings", "PreviewEnabled", 1), // LC_PROFILE_PREVIEW_ENABLED
lcProfileEntry("Settings", "PreviewSize", 300), // LC_PROFILE_PREVIEW_SIZE
lcProfileEntry("Settings", "PreviewLocation", (int)lcPreviewLocation::BottomRight), // LC_PROFILE_PREVIEW_LOCATION
lcProfileEntry("Settings", "PreviewPosition", (int)lcPreviewPosition::Dockable), // LC_PROFILE_PREVIEW_POSITION
lcProfileEntry("Settings", "DrawPreviewAxis", 0), // LC_PROFILE_PREVIEW_DRAW_AXES
lcProfileEntry("Settings", "DrawPreviewViewSphere",1) // LC_PROFILE_PREVIEW_DRAW_VIEW_SPHERE
};
void lcRemoveProfileKey(LC_PROFILE_KEY Key)

View file

@ -80,6 +80,18 @@ enum LC_PROFILE_KEY
LC_PROFILE_POVRAY_WIDTH,
LC_PROFILE_POVRAY_HEIGHT,
LC_PROFILE_PREVIEW_ACTIVE_COLOR,
LC_PROFILE_PREVIEW_VIEW_SPHERE_ENABLED,
LC_PROFILE_PREVIEW_VIEW_SPHERE_SIZE,
LC_PROFILE_PREVIEW_VIEW_SPHERE_LOCATION,
LC_PROFILE_PREVIEW_ENABLED,
LC_PROFILE_PREVIEW_SIZE,
LC_PROFILE_PREVIEW_LOCATION,
LC_PROFILE_PREVIEW_POSITION,
LC_PROFILE_PREVIEW_DRAW_AXES,
LC_PROFILE_PREVIEW_DRAW_VIEW_SPHERE,
LC_NUM_PROFILE_KEYS
};
@ -132,4 +144,3 @@ void lcSetProfileFloat(LC_PROFILE_KEY Key, float Value);
void lcSetProfileString(LC_PROFILE_KEY Key, const QString& Value);
void lcSetProfileStringList(LC_PROFILE_KEY Key, const QStringList& Value);
void lcSetProfileBuffer(LC_PROFILE_KEY Key, const QByteArray& Buffer);

View file

@ -5,6 +5,9 @@
#include "pieceinf.h"
#include "lc_mainwindow.h"
#include "lc_qglwidget.h"
#include "lc_previewwidget.h"
lcTimelineWidget::lcTimelineWidget(QWidget* Parent)
: QTreeWidget(Parent)
{
@ -507,6 +510,96 @@ void lcTimelineWidget::mousePressEvent(QMouseEvent* Event)
QTreeWidget::mousePressEvent(Event);
}
void lcTimelineWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
QTreeWidget::mouseDoubleClickEvent(event);
if ( event->button() == Qt::LeftButton ) {
QTreeWidgetItem* CurrentItem = currentItem();
PreviewSelection(CurrentItem);
}
}
void lcTimelineWidget::PreviewSelection(QTreeWidgetItem* Current)
{
lcPiece* Piece = (lcPiece*)Current->data(0, Qt::UserRole).value<uintptr_t>();
if (!Piece)
return;
PieceInfo* Info = Piece->mPieceInfo;
if (!Info)
return;
bool IsSubfile = Info->IsModel();
QString PartType = Info->mFileName;
quint32 ColorCode = IsSubfile ? 16 : Piece->mColorCode;
const lcPreferences& Preferences = lcGetPreferences();
if (Preferences.mPreviewPosition != lcPreviewPosition::Floating) {
emit gMainWindow->PreviewPiece(PartType, ColorCode);
return;
}
if (!Preferences.mPreviewEnabled)
return;
QString TypeLabel = IsSubfile ? "Submodel" : "Part";
QString WindowTitle = QString("%1 Preview").arg(TypeLabel);
lcPreviewWidget *Preview = new lcPreviewWidget();
lcQGLWidget *ViewWidget = new lcQGLWidget(nullptr, Preview, true/*isView*/, true/*isPreview*/);
if (Preview && ViewWidget) {
if (!Preview->SetCurrentPiece(PartType, ColorCode))
QMessageBox::critical(gMainWindow, tr("Error"), tr("Part preview for %1 failed.").arg(PartType));
ViewWidget->setWindowTitle(WindowTitle);
int Size[2] = { 300,200 };
if (Preferences.mPreviewSize == 400) {
Size[0] = 400; Size[1] = 300;
}
ViewWidget->preferredSize = QSize(Size[0], Size[1]);
float Scale = ViewWidget->deviceScale();
Preview->mWidth = ViewWidget->width() * Scale;
Preview->mHeight = ViewWidget->height() * Scale;
const QRect desktop = QApplication::desktop()->geometry();
QPoint pos;
switch (Preferences.mPreviewLocation)
{
case lcPreviewLocation::TopRight:
pos = mapToGlobal(rect().topRight());
break;
case lcPreviewLocation::TopLeft:
pos = mapToGlobal(rect().topLeft());
break;
case lcPreviewLocation::BottomRight:
pos = mapToGlobal(rect().bottomRight());
break;
default:
pos = mapToGlobal(rect().bottomLeft());
break;
}
if (pos.x() < desktop.left())
pos.setX(desktop.left());
if (pos.y() < desktop.top())
pos.setY(desktop.top());
if ((pos.x() + ViewWidget->width()) > desktop.width())
pos.setX(desktop.width() - ViewWidget->width());
if ((pos.y() + ViewWidget->height()) > desktop.bottom())
pos.setY(desktop.bottom() - ViewWidget->height());
ViewWidget->move(pos);
ViewWidget->setMinimumSize(100,100);
ViewWidget->show();
ViewWidget->setFocus();
} else {
QMessageBox::critical(gMainWindow, tr("Error"), tr("Preview %1 failed.").arg(Info->mFileName));
}
}
void lcTimelineWidget::UpdateModel()
{
QList<QPair<lcPiece*, lcStep>> PieceSteps;

View file

@ -21,10 +21,12 @@ public slots:
void CurrentItemChanged(QTreeWidgetItem* Current, QTreeWidgetItem* Previous);
void ItemSelectionChanged();
void CustomMenuRequested(QPoint Pos);
void PreviewSelection(QTreeWidgetItem* Current);
protected:
void dropEvent(QDropEvent* DropEvent) override;
void mousePressEvent(QMouseEvent* MouseEvent) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void UpdateModel();
void UpdateCurrentStepItem();
@ -33,4 +35,3 @@ protected:
QTreeWidgetItem* mCurrentStepItem;
bool mIgnoreUpdates;
};

View file

@ -1,6 +1,8 @@
#include "lc_global.h"
#include "lc_viewsphere.h"
#include "view.h"
#include "lc_previewwidget.h"
#include "lc_context.h"
#include "lc_stringcache.h"
#include "lc_application.h"
@ -15,14 +17,25 @@ const float lcViewSphere::mHighlightRadius = 0.35f;
const int lcViewSphere::mSubdivisions = 7;
lcViewSphere::lcViewSphere(View* View)
: mView(View)
: mPreview(nullptr),
mView(View),
mIsPreview(false)
{
mMouseDown = false;
}
lcViewSphere::lcViewSphere(lcPreviewWidget* Preview)
: mPreview(Preview),
mView(nullptr),
mIsPreview(true)
{
mMouseDown = false;
mViewSphereSize = lcGetPreferences().mPreviewViewSphereSize;
}
lcMatrix44 lcViewSphere::GetViewMatrix() const
{
lcMatrix44 ViewMatrix = mView->mCamera->mWorldView;
lcMatrix44 ViewMatrix = mIsPreview ? mPreview->GetCamera()->mWorldView : mView->mCamera->mWorldView;
ViewMatrix.SetTranslation(lcVector3(0, 0, 0));
return ViewMatrix;
}
@ -152,15 +165,15 @@ void lcViewSphere::DestroyResources(lcContext* Context)
void lcViewSphere::Draw()
{
const lcPreferences& Preferences = lcGetPreferences();
int ViewportSize = Preferences.mViewSphereSize;
int ViewportSize = mIsPreview ? mViewSphereSize : Preferences.mViewSphereSize;
if (ViewportSize == 0 || !Preferences.mViewSphereEnabled)
return;
lcContext* Context = mView->mContext;
int Width = mView->mWidth;
int Height = mView->mHeight;
lcViewSphereLocation Location = Preferences.mViewSphereLocation;
lcContext* Context = mIsPreview ? mPreview->mContext : mView->mContext;
int Width = mIsPreview ? mPreview->mWidth : mView->mWidth;
int Height = mIsPreview ? mPreview->mHeight : mView->mHeight;
lcViewSphereLocation Location = mIsPreview ? Preferences.mPreviewViewSphereLocation : Preferences.mViewSphereLocation;
int Left = (Location == lcViewSphereLocation::BottomLeft || Location == lcViewSphereLocation::TopLeft) ? 0 : Width - ViewportSize;
int Bottom = (Location == lcViewSphereLocation::BottomLeft || Location == lcViewSphereLocation::BottomRight) ? 0 : Height - ViewportSize;
@ -221,7 +234,7 @@ void lcViewSphere::Draw()
bool lcViewSphere::OnLeftButtonDown()
{
const lcPreferences& Preferences = lcGetPreferences();
if (Preferences.mViewSphereSize == 0 || !Preferences.mViewSphereEnabled)
if ((mIsPreview ? !mViewSphereSize : !Preferences.mViewSphereSize) || !Preferences.mViewSphereEnabled)
return false;
mIntersectionFlags = GetIntersectionFlags(mIntersection);
@ -229,8 +242,8 @@ bool lcViewSphere::OnLeftButtonDown()
if (!mIntersectionFlags.any())
return false;
mMouseDownX = mView->mInputState.x;
mMouseDownY = mView->mInputState.y;
mMouseDownX = mIsPreview ? mPreview->mInputState.x : mView->mInputState.x;
mMouseDownY = mIsPreview ? mPreview->mInputState.y : mView->mInputState.y;
mMouseDown = true;
return true;
@ -239,7 +252,7 @@ bool lcViewSphere::OnLeftButtonDown()
bool lcViewSphere::OnLeftButtonUp()
{
const lcPreferences& Preferences = lcGetPreferences();
if (Preferences.mViewSphereSize == 0 || !Preferences.mViewSphereEnabled)
if ((mIsPreview ? !mViewSphereSize : !Preferences.mViewSphereSize) || !Preferences.mViewSphereEnabled)
return false;
if (!mMouseDown)
@ -260,7 +273,7 @@ bool lcViewSphere::OnLeftButtonUp()
Position[AxisIdx] = -1250.0f;
}
mView->SetViewpoint(Position);
mIsPreview ? mPreview->SetViewpoint(Position) : mView->SetViewpoint(Position);
return true;
}
@ -268,17 +281,17 @@ bool lcViewSphere::OnLeftButtonUp()
bool lcViewSphere::OnMouseMove()
{
const lcPreferences& Preferences = lcGetPreferences();
if (Preferences.mViewSphereSize == 0 || !Preferences.mViewSphereEnabled)
if ((mIsPreview ? !mViewSphereSize : !Preferences.mViewSphereSize) || !Preferences.mViewSphereEnabled)
return false;
if (IsDragging())
{
mIntersectionFlags.reset();
mView->StartOrbitTracking();
mIsPreview ? mPreview->StartOrbitTracking() : mView->StartOrbitTracking();
return true;
}
if (mView->IsTracking())
if (mIsPreview ? mPreview->IsTracking() : mView->IsTracking())
return false;
std::bitset<6> IntersectionFlags = GetIntersectionFlags(mIntersection);
@ -286,7 +299,7 @@ bool lcViewSphere::OnMouseMove()
if (IntersectionFlags != mIntersectionFlags)
{
mIntersectionFlags = IntersectionFlags;
mView->Redraw();
mIsPreview ? mPreview->Redraw() : mView->Redraw();
}
return mIntersectionFlags.any();
@ -294,21 +307,23 @@ bool lcViewSphere::OnMouseMove()
bool lcViewSphere::IsDragging() const
{
return mMouseDown && (qAbs(mMouseDownX - mView->mInputState.x) > 3 || qAbs(mMouseDownY - mView->mInputState.y) > 3);
int InputStateX = mIsPreview ? mPreview->mInputState.x : mView->mInputState.x;
int InputStateY = mIsPreview ? mPreview->mInputState.y : mView->mInputState.y;
return mMouseDown && (qAbs(mMouseDownX - InputStateX) > 3 || qAbs(mMouseDownY - InputStateY) > 3);
}
std::bitset<6> lcViewSphere::GetIntersectionFlags(lcVector3& Intersection) const
{
const lcPreferences& Preferences = lcGetPreferences();
lcViewSphereLocation Location = Preferences.mViewSphereLocation;
lcViewSphereLocation Location = mIsPreview ? Preferences.mPreviewViewSphereLocation : Preferences.mViewSphereLocation;
int Width = mView->mWidth;
int Height = mView->mHeight;
int ViewportSize = Preferences.mViewSphereSize;
int Width = mIsPreview ? mPreview->mWidth : mView->mWidth;
int Height = mIsPreview ? mPreview->mHeight : mView->mHeight;
int ViewportSize = mIsPreview ? mViewSphereSize : Preferences.mViewSphereSize;
int Left = (Location == lcViewSphereLocation::BottomLeft || Location == lcViewSphereLocation::TopLeft) ? 0 : Width - ViewportSize;
int Bottom = (Location == lcViewSphereLocation::BottomLeft || Location == lcViewSphereLocation::BottomRight) ? 0 : Height - ViewportSize;
int x = mView->mInputState.x - Left;
int y = mView->mInputState.y - Bottom;
int x = (mIsPreview ? mPreview->mInputState.x : mView->mInputState.x) - Left;
int y = (mIsPreview ? mPreview->mInputState.y : mView->mInputState.y) - Bottom;
std::bitset<6> IntersectionFlags;
if (x < 0 || x > Width || y < 0 || y > Height)

View file

@ -5,11 +5,13 @@
#include <bitset>
class View;
class lcPreviewWidget;
class lcViewSphere
{
public:
lcViewSphere(View* View);
lcViewSphere(View *View);
lcViewSphere(lcPreviewWidget *Preview);
void Draw();
bool OnMouseMove();
@ -25,12 +27,15 @@ protected:
lcMatrix44 GetProjectionMatrix() const;
std::bitset<6> GetIntersectionFlags(lcVector3& Intersection) const;
lcPreviewWidget* mPreview;
View* mView;
lcVector3 mIntersection;
std::bitset<6> mIntersectionFlags;
int mViewSphereSize;
int mMouseDownX;
int mMouseDownY;
bool mMouseDown;
bool mIsPreview;
static lcTexture* mTexture;
static lcVertexBuffer mVertexBuffer;

View file

@ -60,15 +60,17 @@ void lcHTMLExportOptions::SaveDefaults()
lcSetProfileInt(LC_PROFILE_HTML_IMAGE_HEIGHT, StepImagesHeight);
}
Project::Project()
Project::Project(bool IsPreview)
: mIsPreview(IsPreview)
{
mModified = false;
mActiveModel = new lcModel(tr("New Model.ldr"));
mActiveModel = new lcModel(tr(mIsPreview ? "Preview.ldr" : "New Model.ldr"), mIsPreview);
mActiveModel->CreatePieceInfo(this);
mActiveModel->SetSaved();
mModels.Add(mActiveModel);
QObject::connect(&mFileWatcher, SIGNAL(fileChanged(const QString&)), gMainWindow, SLOT(ProjectFileChanged(const QString&)));
if (!mIsPreview)
QObject::connect(&mFileWatcher, SIGNAL(fileChanged(const QString&)), gMainWindow, SLOT(ProjectFileChanged(const QString&)));
}
Project::~Project()
@ -149,8 +151,10 @@ void Project::SetActiveModel(int ModelIndex)
mModels[ModelIdx]->UpdatePieceInfo(UpdatedModels);
mActiveModel = mModels[ModelIndex];
gMainWindow->SetCurrentModelTab(mActiveModel);
mActiveModel->UpdateInterface();
if (!mIsPreview) {
gMainWindow->SetCurrentModelTab(mActiveModel);
mActiveModel->UpdateInterface();
}
}
void Project::SetActiveModel(const QString& FileName)
@ -346,10 +350,10 @@ void Project::SetFileName(const QString& FileName)
if (mFileName == FileName)
return;
if (!mFileName.isEmpty())
if (!mIsPreview && !mFileName.isEmpty())
mFileWatcher.removePath(mFileName);
if (!FileName.isEmpty())
if (!mIsPreview && !FileName.isEmpty())
mFileWatcher.addPath(FileName);
mFileName = FileName;
@ -357,11 +361,15 @@ void Project::SetFileName(const QString& FileName)
bool Project::Load(const QString& FileName)
{
QWidget *parent = nullptr;
if (!mIsPreview)
parent = gMainWindow;
QFile File(FileName);
if (!File.open(QIODevice::ReadOnly))
{
QMessageBox::warning(gMainWindow, tr("Error"), tr("Error reading file '%1':\n%2").arg(FileName, File.errorString()));
QMessageBox::warning(parent, tr("Error"), tr("Error reading file '%1':\n%2").arg(FileName, File.errorString()));
return false;
}
@ -388,7 +396,7 @@ bool Project::Load(const QString& FileName)
while (!Buffer.atEnd())
{
lcModel* Model = new lcModel(QString());
lcModel* Model = new lcModel(QString(), mIsPreview);
int Pos = Model->SplitMPD(Buffer);
if (Models.empty() || !Model->GetFileName().isEmpty())
@ -415,7 +423,7 @@ bool Project::Load(const QString& FileName)
MemFile.WriteBuffer(FileData.constData(), FileData.size());
MemFile.Seek(0, SEEK_SET);
lcModel* Model = new lcModel(QString());
lcModel* Model = new lcModel(QString(), mIsPreview);
if (Model->LoadBinary(&MemFile))
{
@ -429,7 +437,7 @@ bool Project::Load(const QString& FileName)
if (mModels.IsEmpty())
{
QMessageBox::warning(gMainWindow, tr("Error"), tr("Error loading file '%1':\nFile format is not recognized.").arg(FileName));
QMessageBox::warning(parent, tr("Error"), tr("Error loading file '%1':\nFile format is not recognized.").arg(FileName));
return false;
}

View file

@ -41,7 +41,7 @@ struct lcInstructionsPageLayout;
class Project
{
public:
Project();
Project(bool IsPreview = false);
~Project();
Project(const Project&) = delete;
@ -115,6 +115,7 @@ protected:
std::vector<lcModelPartsEntry> GetModelParts();
void SetFileName(const QString& FileName);
bool mIsPreview;
bool mModified;
QString mFileName;
QFileSystemWatcher mFileWatcher;

View file

@ -166,153 +166,155 @@ macx {
}
SOURCES += common/view.cpp \
common/lc_instructionsdialog.cpp \
common/texfont.cpp \
common/project.cpp \
common/pieceinf.cpp \
common/piece.cpp \
common/object.cpp \
common/minifig.cpp \
common/light.cpp \
common/lc_application.cpp \
common/lc_category.cpp \
common/lc_colors.cpp \
common/lc_commands.cpp \
common/lc_context.cpp \
common/lc_file.cpp \
common/lc_glextensions.cpp \
common/lc_http.cpp \
common/lc_library.cpp \
common/lc_lxf.cpp \
common/lc_mainwindow.cpp \
common/lc_mesh.cpp \
common/lc_meshloader.cpp \
common/lc_model.cpp \
common/lc_profile.cpp \
common/lc_scene.cpp \
common/lc_selectbycolordialog.cpp \
common/lc_shortcuts.cpp \
common/lc_stringcache.cpp \
common/lc_synth.cpp \
common/lc_texture.cpp \
common/lc_viewsphere.cpp \
common/lc_zipfile.cpp \
common/image.cpp \
common/group.cpp \
common/camera.cpp \
qt/system.cpp \
qt/qtmain.cpp \
qt/lc_qarraydialog.cpp \
qt/lc_qgroupdialog.cpp \
qt/lc_qaboutdialog.cpp \
qt/lc_qeditgroupsdialog.cpp \
qt/lc_qselectdialog.cpp \
qt/lc_qpropertiesdialog.cpp \
qt/lc_qhtmldialog.cpp \
qt/lc_qminifigdialog.cpp \
qt/lc_qpreferencesdialog.cpp \
qt/lc_qcategorydialog.cpp \
qt/lc_qimagedialog.cpp \
qt/lc_qupdatedialog.cpp \
qt/lc_qutils.cpp \
qt/lc_qpropertiestree.cpp \
qt/lc_qcolorpicker.cpp \
qt/lc_qglwidget.cpp \
qt/lc_qcolorlist.cpp \
qt/lc_qfinddialog.cpp \
qt/lc_qmodellistdialog.cpp \
common/lc_partselectionwidget.cpp \
common/lc_timelinewidget.cpp \
qt/lc_renderdialog.cpp \
qt/lc_setsdatabasedialog.cpp \
common/lc_partpalettedialog.cpp
common/lc_instructionsdialog.cpp \
common/lc_previewwidget.cpp \
common/texfont.cpp \
common/project.cpp \
common/pieceinf.cpp \
common/piece.cpp \
common/object.cpp \
common/minifig.cpp \
common/light.cpp \
common/lc_application.cpp \
common/lc_category.cpp \
common/lc_colors.cpp \
common/lc_commands.cpp \
common/lc_context.cpp \
common/lc_file.cpp \
common/lc_glextensions.cpp \
common/lc_http.cpp \
common/lc_library.cpp \
common/lc_lxf.cpp \
common/lc_mainwindow.cpp \
common/lc_mesh.cpp \
common/lc_meshloader.cpp \
common/lc_model.cpp \
common/lc_profile.cpp \
common/lc_scene.cpp \
common/lc_selectbycolordialog.cpp \
common/lc_shortcuts.cpp \
common/lc_stringcache.cpp \
common/lc_synth.cpp \
common/lc_texture.cpp \
common/lc_viewsphere.cpp \
common/lc_zipfile.cpp \
common/image.cpp \
common/group.cpp \
common/camera.cpp \
qt/system.cpp \
qt/qtmain.cpp \
qt/lc_qarraydialog.cpp \
qt/lc_qgroupdialog.cpp \
qt/lc_qaboutdialog.cpp \
qt/lc_qeditgroupsdialog.cpp \
qt/lc_qselectdialog.cpp \
qt/lc_qpropertiesdialog.cpp \
qt/lc_qhtmldialog.cpp \
qt/lc_qminifigdialog.cpp \
qt/lc_qpreferencesdialog.cpp \
qt/lc_qcategorydialog.cpp \
qt/lc_qimagedialog.cpp \
qt/lc_qupdatedialog.cpp \
qt/lc_qutils.cpp \
qt/lc_qpropertiestree.cpp \
qt/lc_qcolorpicker.cpp \
qt/lc_qglwidget.cpp \
qt/lc_qcolorlist.cpp \
qt/lc_qfinddialog.cpp \
qt/lc_qmodellistdialog.cpp \
common/lc_partselectionwidget.cpp \
common/lc_timelinewidget.cpp \
qt/lc_renderdialog.cpp \
qt/lc_setsdatabasedialog.cpp \
common/lc_partpalettedialog.cpp
HEADERS += \
common/lc_instructionsdialog.h \
common/view.h \
common/texfont.h \
common/project.h \
common/pieceinf.h \
common/piece.h \
common/object.h \
common/minifig.h \
common/light.h \
common/lc_application.h \
common/lc_array.h \
common/lc_basewindow.h \
common/lc_category.h \
common/lc_colors.h \
common/lc_commands.h \
common/lc_context.h \
common/lc_file.h \
common/lc_glext.h \
common/lc_glextensions.h \
common/lc_global.h \
common/lc_glwidget.h \
common/lc_http.h \
common/lc_library.h \
common/lc_lxf.h \
common/lc_mainwindow.h \
common/lc_math.h \
common/lc_mesh.h \
common/lc_meshloader.h \
common/lc_model.h \
common/lc_profile.h \
common/lc_scene.h \
common/lc_selectbycolordialog.h \
common/lc_shortcuts.h \
common/lc_stringcache.h \
common/lc_synth.h \
common/lc_texture.h \
common/lc_viewsphere.h \
common/lc_zipfile.h \
common/image.h \
common/group.h \
common/camera.h \
qt/lc_qarraydialog.h \
qt/lc_qgroupdialog.h \
qt/lc_qaboutdialog.h \
qt/lc_qeditgroupsdialog.h \
qt/lc_qselectdialog.h \
qt/lc_qpropertiesdialog.h \
qt/lc_qhtmldialog.h \
qt/lc_qminifigdialog.h \
qt/lc_qpreferencesdialog.h \
qt/lc_qcategorydialog.h \
qt/lc_qimagedialog.h \
qt/lc_qupdatedialog.h \
qt/lc_qutils.h \
qt/lc_qpropertiestree.h \
qt/lc_qcolorpicker.h \
qt/lc_qglwidget.h \
qt/lc_qcolorlist.h \
qt/lc_qfinddialog.h \
qt/lc_qmodellistdialog.h \
common/lc_partselectionwidget.h \
common/lc_timelinewidget.h \
qt/lc_renderdialog.h \
qt/lc_setsdatabasedialog.h \
common/lc_partpalettedialog.h
common/lc_instructionsdialog.h \
common/lc_previewwidget.h \
common/view.h \
common/texfont.h \
common/project.h \
common/pieceinf.h \
common/piece.h \
common/object.h \
common/minifig.h \
common/light.h \
common/lc_application.h \
common/lc_array.h \
common/lc_basewindow.h \
common/lc_category.h \
common/lc_colors.h \
common/lc_commands.h \
common/lc_context.h \
common/lc_file.h \
common/lc_glext.h \
common/lc_glextensions.h \
common/lc_global.h \
common/lc_glwidget.h \
common/lc_http.h \
common/lc_library.h \
common/lc_lxf.h \
common/lc_mainwindow.h \
common/lc_math.h \
common/lc_mesh.h \
common/lc_meshloader.h \
common/lc_model.h \
common/lc_profile.h \
common/lc_scene.h \
common/lc_selectbycolordialog.h \
common/lc_shortcuts.h \
common/lc_stringcache.h \
common/lc_synth.h \
common/lc_texture.h \
common/lc_viewsphere.h \
common/lc_zipfile.h \
common/image.h \
common/group.h \
common/camera.h \
qt/lc_qarraydialog.h \
qt/lc_qgroupdialog.h \
qt/lc_qaboutdialog.h \
qt/lc_qeditgroupsdialog.h \
qt/lc_qselectdialog.h \
qt/lc_qpropertiesdialog.h \
qt/lc_qhtmldialog.h \
qt/lc_qminifigdialog.h \
qt/lc_qpreferencesdialog.h \
qt/lc_qcategorydialog.h \
qt/lc_qimagedialog.h \
qt/lc_qupdatedialog.h \
qt/lc_qutils.h \
qt/lc_qpropertiestree.h \
qt/lc_qcolorpicker.h \
qt/lc_qglwidget.h \
qt/lc_qcolorlist.h \
qt/lc_qfinddialog.h \
qt/lc_qmodellistdialog.h \
common/lc_partselectionwidget.h \
common/lc_timelinewidget.h \
qt/lc_renderdialog.h \
qt/lc_setsdatabasedialog.h \
common/lc_partpalettedialog.h
FORMS += \
qt/lc_qarraydialog.ui \
qt/lc_qgroupdialog.ui \
qt/lc_qaboutdialog.ui \
qt/lc_qeditgroupsdialog.ui \
qt/lc_qselectdialog.ui \
qt/lc_qpropertiesdialog.ui \
qt/lc_qhtmldialog.ui \
qt/lc_qminifigdialog.ui \
qt/lc_qpreferencesdialog.ui \
qt/lc_qcategorydialog.ui \
qt/lc_qimagedialog.ui \
qt/lc_qupdatedialog.ui \
qt/lc_qfinddialog.ui \
qt/lc_qmodellistdialog.ui \
qt/lc_renderdialog.ui \
qt/lc_setsdatabasedialog.ui \
common/lc_partpalettedialog.ui
qt/lc_qarraydialog.ui \
qt/lc_qgroupdialog.ui \
qt/lc_qaboutdialog.ui \
qt/lc_qeditgroupsdialog.ui \
qt/lc_qselectdialog.ui \
qt/lc_qpropertiesdialog.ui \
qt/lc_qhtmldialog.ui \
qt/lc_qminifigdialog.ui \
qt/lc_qpreferencesdialog.ui \
qt/lc_qcategorydialog.ui \
qt/lc_qimagedialog.ui \
qt/lc_qupdatedialog.ui \
qt/lc_qfinddialog.ui \
qt/lc_qmodellistdialog.ui \
qt/lc_renderdialog.ui \
qt/lc_setsdatabasedialog.ui \
common/lc_partpalettedialog.ui
OTHER_FILES +=
RESOURCES += leocad.qrc resources/stylesheet/stylesheet.qrc
!win32 {
TRANSLATIONS = resources/leocad_pt.ts resources/leocad_fr.ts resources/leocad_de.ts resources/leocad_uk.ts resources/leocad_cs.ts resources/leocad_es.ts
TRANSLATIONS = resources/leocad_pt.ts resources/leocad_fr.ts resources/leocad_de.ts resources/leocad_uk.ts resources/leocad_cs.ts resources/leocad_es.ts
}

View file

@ -84,8 +84,8 @@ void lcGLWidget::SetCursor(lcCursor CursorType)
}
}
lcQGLWidget::lcQGLWidget(QWidget *parent, lcGLWidget *owner, bool view)
: QGLWidget(parent, gWidgetList.isEmpty() ? nullptr : gWidgetList.first())
lcQGLWidget::lcQGLWidget(QWidget *parent, lcGLWidget *owner, bool IsView, bool IsPreview)
: QGLWidget(parent, gWidgetList.isEmpty() ? nullptr : gWidgetList.first()), mIsPreview(IsPreview)
{
mWheelAccumulator = 0;
widget = owner;
@ -110,8 +110,11 @@ lcQGLWidget::lcQGLWidget(QWidget *parent, lcGLWidget *owner, bool view)
if (!gSupportsShaderObjects && lcGetPreferences().mShadingMode == lcShadingMode::DefaultLights)
lcGetPreferences().mShadingMode = lcShadingMode::Flat;
if (!gSupportsFramebufferObjectARB && !gSupportsFramebufferObjectEXT)
gMainWindow->GetPartSelectionWidget()->DisableIconMode();
if (!mIsPreview) {
if (!gSupportsFramebufferObjectARB && !gSupportsFramebufferObjectEXT) {
gMainWindow->GetPartSelectionWidget()->DisableIconMode();
}
}
gPlaceholderMesh = new lcMesh;
gPlaceholderMesh->CreateBox();
@ -124,11 +127,12 @@ lcQGLWidget::lcQGLWidget(QWidget *parent, lcGLWidget *owner, bool view)
preferredSize = QSize(0, 0);
setMouseTracking(true);
mIsView = view;
mIsView = IsView;
if (mIsView)
{
setFocusPolicy(Qt::StrongFocus);
setAcceptDrops(true);
if (!mIsPreview)
setAcceptDrops(true);
}
}
@ -142,7 +146,8 @@ lcQGLWidget::~lcQGLWidget()
gTexFont.Reset();
lcGetPiecesLibrary()->ReleaseBuffers(widget->mContext);
View::DestroyResources(widget->mContext);
if (!mIsPreview)
View::DestroyResources(widget->mContext);
lcContext::DestroyResources();
lcViewSphere::DestroyResources(widget->mContext);
@ -180,7 +185,7 @@ void lcQGLWidget::paintGL()
void lcQGLWidget::keyPressEvent(QKeyEvent *event)
{
if (mIsView && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Shift))
if (!mIsPreview && mIsView && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Shift))
{
widget->mInputState.Modifiers = event->modifiers();
widget->OnUpdateCursor();
@ -191,7 +196,7 @@ void lcQGLWidget::keyPressEvent(QKeyEvent *event)
void lcQGLWidget::keyReleaseEvent(QKeyEvent *event)
{
if (mIsView && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Shift))
if (!mIsPreview && mIsView && (event->key() == Qt::Key_Control || event->key() == Qt::Key_Shift))
{
widget->mInputState.Modifiers = event->modifiers();
widget->OnUpdateCursor();
@ -335,7 +340,7 @@ void lcQGLWidget::wheelEvent(QWheelEvent *event)
void lcQGLWidget::dragEnterEvent(QDragEnterEvent* DragEnterEvent)
{
if (mIsView)
if (!mIsPreview && mIsView)
{
const QMimeData* MimeData = DragEnterEvent->mimeData();
@ -356,8 +361,9 @@ void lcQGLWidget::dragEnterEvent(QDragEnterEvent* DragEnterEvent)
void lcQGLWidget::dragLeaveEvent(QDragLeaveEvent *event)
{
if (!mIsView)
if (!mIsView || mIsPreview) {
return;
}
((View*)widget)->EndDrag(false);
@ -366,7 +372,7 @@ void lcQGLWidget::dragLeaveEvent(QDragLeaveEvent *event)
void lcQGLWidget::dragMoveEvent(QDragMoveEvent* DragMoveEvent)
{
if (mIsView)
if (!mIsPreview && mIsView)
{
const QMimeData* MimeData = DragMoveEvent->mimeData();
@ -390,7 +396,7 @@ void lcQGLWidget::dragMoveEvent(QDragMoveEvent* DragMoveEvent)
void lcQGLWidget::dropEvent(QDropEvent* DropEvent)
{
if (mIsView)
if (!mIsPreview && mIsView)
{
const QMimeData* MimeData = DropEvent->mimeData();

View file

@ -6,7 +6,7 @@ class lcGLWidget;
class lcQGLWidget : public QGLWidget
{
public:
lcQGLWidget(QWidget* Parent, lcGLWidget* Owner, bool IsView);
lcQGLWidget(QWidget* Parent, lcGLWidget* Owner, bool IsView, bool IsPreview = false);
~lcQGLWidget();
QSize sizeHint() const override;
@ -14,6 +14,7 @@ public:
lcGLWidget *widget;
QSize preferredSize;
bool mIsView;
bool mIsPreview;
float deviceScale()
{

View file

@ -123,6 +123,55 @@ lcQPreferencesDialog::lcQPreferencesDialog(QWidget* Parent, lcPreferencesDialogO
else
ui->ViewSphereSizeCombo->setCurrentIndex(0);
ui->PreviewAxisIconCheckBox->setChecked(mOptions->Preferences.mDrawPreviewAxis);
ui->PreviewViewSphereCheckBox->setChecked(mOptions->Preferences.mDrawPreviewViewSphere);
ui->PreviewLocationCombo->setCurrentIndex((int)mOptions->Preferences.mPreviewLocation);
ui->PreviewPositionCombo->setCurrentIndex((int)mOptions->Preferences.mPreviewPosition);
if (mOptions->Preferences.mPreviewEnabled)
{
switch (mOptions->Preferences.mPreviewSize)
{
case 400:
ui->PreviewSizeCombo->setCurrentIndex(2);
break;
case 300:
ui->PreviewSizeCombo->setCurrentIndex(1);
break;
default: /*Disabled*/
ui->PreviewSizeCombo->setCurrentIndex(0);
break;
}
}
else
ui->PreviewSizeCombo->setCurrentIndex(0);
ui->PreviewViewSphereLocationCombo->setCurrentIndex((int)mOptions->Preferences.mPreviewViewSphereLocation);
if (mOptions->Preferences.mPreviewViewSphereEnabled)
{
switch (mOptions->Preferences.mPreviewViewSphereSize)
{
case 100:
ui->PreviewViewSphereSizeCombo->setCurrentIndex(3);
break;
case 75:
ui->PreviewViewSphereSizeCombo->setCurrentIndex(2);
break;
case 50:
ui->PreviewViewSphereSizeCombo->setCurrentIndex(1);
break;
default:
ui->PreviewViewSphereSizeCombo->setCurrentIndex(0);
break;
}
}
else
ui->PreviewViewSphereSizeCombo->setCurrentIndex(0);
ui->studLogo->setChecked(mOptions->StudLogo);
if (ui->studLogo->isChecked())
ui->studLogoCombo->setCurrentIndex(mOptions->StudLogo - 1);
@ -176,6 +225,13 @@ lcQPreferencesDialog::lcQPreferencesDialog(QWidget* Parent, lcPreferencesDialogO
on_gridLines_toggled();
on_ViewSphereSizeCombo_currentIndexChanged(ui->ViewSphereSizeCombo->currentIndex());
on_PreviewViewSphereSizeCombo_currentIndexChanged(ui->PreviewViewSphereSizeCombo->currentIndex());
on_PreviewSizeCombo_currentIndexChanged(ui->PreviewSizeCombo->currentIndex());
on_PreviewPositionCombo_currentIndexChanged(ui->PreviewPositionCombo->currentIndex());
ui->PreviewLocationCombo->setEnabled(
ui->PreviewSizeCombo->currentIndex() != 0 &&
ui->PreviewPositionCombo->currentIndex() != 0);
updateCategories();
ui->categoriesTree->setCurrentItem(ui->categoriesTree->topLevelItem(0));
@ -220,7 +276,7 @@ void lcQPreferencesDialog::accept()
mOptions->Preferences.mColorTheme = static_cast<lcColorTheme>(ui->ColorTheme->currentIndex());
int Language = ui->Language->currentIndex();
if (Language < 0 || Language > static_cast<int>(LC_ARRAY_COUNT(gLanguageLocales)))
if (Language < 0 || Language > static_cast<int>(LC_ARRAY_COUNT(gLanguageLocales)))
Language = 0;
mOptions->Language = gLanguageLocales[Language];
@ -275,6 +331,44 @@ void lcQPreferencesDialog::accept()
else
mOptions->StudLogo = 0;
mOptions->Preferences.mDrawPreviewAxis = ui->PreviewAxisIconCheckBox->isChecked();
mOptions->Preferences.mDrawPreviewViewSphere = ui->PreviewViewSphereCheckBox->isChecked();
mOptions->Preferences.mPreviewLocation = (lcPreviewLocation)ui->PreviewLocationCombo->currentIndex();
mOptions->Preferences.mPreviewPosition = (lcPreviewPosition)ui->PreviewPositionCombo->currentIndex();
switch (ui->PreviewSizeCombo->currentIndex())
{
case 2:
mOptions->Preferences.mPreviewSize = 400;
break;
case 1:
mOptions->Preferences.mPreviewSize = 300;
break;
default:
mOptions->Preferences.mPreviewEnabled = 0;
break;
}
mOptions->Preferences.mPreviewViewSphereLocation = (lcViewSphereLocation)ui->PreviewViewSphereLocationCombo->currentIndex();
switch (ui->PreviewViewSphereSizeCombo->currentIndex())
{
case 3:
mOptions->Preferences.mPreviewViewSphereSize = 100;
break;
case 2:
mOptions->Preferences.mPreviewViewSphereSize = 75;
break;
case 1:
mOptions->Preferences.mPreviewViewSphereSize = 50;
break;
default:
break;
}
QDialog::accept();
}
@ -473,6 +567,26 @@ void lcQPreferencesDialog::on_gridLines_toggled()
ui->gridLineSpacing->setEnabled(ui->gridLines->isChecked());
}
void lcQPreferencesDialog::on_PreviewViewSphereSizeCombo_currentIndexChanged(int Index)
{
ui->PreviewViewSphereLocationCombo->setEnabled(Index != 0);
}
void lcQPreferencesDialog::on_PreviewSizeCombo_currentIndexChanged(int Index)
{
ui->PreviewLocationCombo->setEnabled(Index != 0);
if (ui->PreviewPositionCombo->currentIndex() != 0)
ui->PreviewPositionCombo->setEnabled(Index != 0);
ui->PreviewAxisIconCheckBox->setEnabled(Index != 0);
ui->PreviewViewSphereCheckBox->setEnabled(Index != 0);
}
void lcQPreferencesDialog::on_PreviewPositionCombo_currentIndexChanged(int Index)
{
ui->PreviewSizeCombo->setEnabled(Index != 0);
ui->PreviewLocationCombo->setEnabled(Index != 0);
}
void lcQPreferencesDialog::on_ViewSphereSizeCombo_currentIndexChanged(int Index)
{
bool Enabled = Index != 0;

View file

@ -65,6 +65,10 @@ public slots:
void on_studLogo_toggled();
void MouseTreeItemChanged(QTreeWidgetItem* Current);
void on_PreviewSizeCombo_currentIndexChanged(int Index);
void on_PreviewViewSphereSizeCombo_currentIndexChanged(int Index);
void on_PreviewPositionCombo_currentIndexChanged(int Index);
private:
Ui::lcQPreferencesDialog *ui;

View file

@ -202,7 +202,7 @@
<item>
<widget class="QToolButton" name="partsLibraryBrowse">
<property name="icon">
<iconset>
<iconset resource="../leocad.qrc">
<normaloff>:/resources/file_open.png</normaloff>:/resources/file_open.png</iconset>
</property>
</widget>
@ -210,7 +210,7 @@
<item>
<widget class="QToolButton" name="partsArchiveBrowse">
<property name="icon">
<iconset>
<iconset resource="../leocad.qrc">
<normaloff>:/resources/archive.png</normaloff>:/resources/archive.png</iconset>
</property>
</widget>
@ -551,7 +551,14 @@
<string>Overlays</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="2">
<item row="0" column="0">
<widget class="QCheckBox" name="AxisIconCheckBox">
<property name="text">
<string>Axis icon</string>
</property>
</widget>
</item>
<item row="0" column="6">
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -564,17 +571,24 @@
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="AxisIconCheckBox">
<item row="0" column="5">
<widget class="QToolButton" name="OverlayColorButton">
<property name="text">
<string>Axis icon</string>
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<item row="0" column="3">
<widget class="QToolButton" name="ActiveViewColorButton">
<property name="text">
<string>Overlay Color:</string>
<string/>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Active View:</string>
</property>
</widget>
</item>
@ -585,24 +599,10 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QToolButton" name="OverlayColorButton">
<item row="0" column="4">
<widget class="QLabel" name="label_2">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Active View:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="ActiveViewColorButton">
<property name="text">
<string/>
<string>Overlay Color:</string>
</property>
</widget>
</item>
@ -719,55 +719,13 @@
</item>
</widget>
</item>
<item row="2" column="5">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Highlight Color:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Size:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QToolButton" name="ViewSphereColorButton">
<item row="2" column="6">
<widget class="QToolButton" name="ViewSphereHighlightColorButton">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QToolButton" name="ViewSphereTextColorButton">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_23">
<property name="text">
<string>Text Color:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_24">
<property name="text">
<string>Location:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="ViewSphereLocationCombo">
<item>
@ -792,13 +750,231 @@
</item>
</widget>
</item>
<item row="2" column="6">
<widget class="QToolButton" name="ViewSphereHighlightColorButton">
<item row="2" column="1">
<widget class="QToolButton" name="ViewSphereColorButton">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Preview Location</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_23">
<property name="text">
<string>Text Color:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_24">
<property name="text">
<string>Location:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="PreviewViewSphereSizeCombo">
<item>
<property name="text">
<string>Disabled</string>
</property>
</item>
<item>
<property name="text">
<string>Small</string>
</property>
</item>
<item>
<property name="text">
<string>Medium</string>
</property>
</item>
<item>
<property name="text">
<string>Large</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Preview Size:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Size:</string>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Highlight Color:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QToolButton" name="ViewSphereTextColorButton">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QComboBox" name="PreviewViewSphereLocationCombo">
<item>
<property name="text">
<string>Top Left</string>
</property>
</item>
<item>
<property name="text">
<string>Top Right</string>
</property>
</item>
<item>
<property name="text">
<string>Bottom Left</string>
</property>
</item>
<item>
<property name="text">
<string>Bottom Right</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="PreviewGroup">
<property name="title">
<string>Preview</string>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="2">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Location:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="PreviewViewSphereCheckBox">
<property name="text">
<string>View Sphere</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QComboBox" name="PreviewPositionCombo">
<item>
<property name="text">
<string>Dockable</string>
</property>
</item>
<item>
<property name="text">
<string>Floating</string>
</property>
</item>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Position:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Size:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="PreviewLocationCombo">
<item>
<property name="text">
<string>Top Left</string>
</property>
</item>
<item>
<property name="text">
<string>Top Right</string>
</property>
</item>
<item>
<property name="text">
<string>Bottom Left</string>
</property>
</item>
<item>
<property name="text">
<string>Bottom Right</string>
</property>
</item>
</widget>
</item>
<item row="1" column="2" colspan="2">
<widget class="QCheckBox" name="PreviewAxisIconCheckBox">
<property name="text">
<string>Axis Icon</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="PreviewSizeCombo">
<item>
<property name="text">
<string>Disabled</string>
</property>
</item>
<item>
<property name="text">
<string>Small</string>
</property>
</item>
<item>
<property name="text">
<string>Large</string>
</property>
</item>
</widget>
</item>
<item row="0" column="6">
<spacer name="horizontalSpacer_11">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
@ -1384,9 +1560,16 @@
<tabstop>gridLineColor</tabstop>
<tabstop>ViewSphereSizeCombo</tabstop>
<tabstop>ViewSphereLocationCombo</tabstop>
<tabstop>PreviewViewSphereSizeCombo</tabstop>
<tabstop>PreviewViewSphereLocationCombo</tabstop>
<tabstop>ViewSphereColorButton</tabstop>
<tabstop>ViewSphereTextColorButton</tabstop>
<tabstop>ViewSphereHighlightColorButton</tabstop>
<tabstop>PreviewSizeCombo</tabstop>
<tabstop>PreviewLocationCombo</tabstop>
<tabstop>PreviewPositionCombo</tabstop>
<tabstop>PreviewViewSphereCheckBox</tabstop>
<tabstop>PreviewAxisIconCheckBox</tabstop>
<tabstop>categoriesTree</tabstop>
<tabstop>partsTree</tabstop>
<tabstop>importCategories</tabstop>
@ -1415,7 +1598,9 @@
<tabstop>mouseRemove</tabstop>
<tabstop>mouseSensitivity</tabstop>
</tabstops>
<resources/>
<resources>
<include location="../leocad.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>