diff --git a/common/lc_application.cpp b/common/lc_application.cpp index 87379814..5c626edd 100644 --- a/common/lc_application.cpp +++ b/common/lc_application.cpp @@ -250,10 +250,13 @@ void lcApplication::SetProject(Project* Project) { SaveTabLayout(); - gMainWindow->RemoveAllModelTabs(); + if (gMainWindow) + { + gMainWindow->RemoveAllModelTabs(); - if (gMainWindow->GetPreviewWidget()) - gMainWindow->GetPreviewWidget()->ClearPreview(); + if (gMainWindow->GetPreviewWidget()) + gMainWindow->GetPreviewWidget()->ClearPreview(); + } delete mProject; mProject = Project; @@ -266,7 +269,8 @@ void lcApplication::SetProject(Project* Project) QSettings Settings; QByteArray TabLayout = Settings.value(GetTabLayoutKey()).toByteArray(); - gMainWindow->RestoreTabLayout(TabLayout); + if (gMainWindow) + gMainWindow->RestoreTabLayout(TabLayout); } } @@ -763,9 +767,14 @@ lcStartupMode lcApplication::Initialize(QList>& LibraryPath return lcStartupMode::Error; #endif - gMainWindow = new lcMainWindow(); - lcLoadDefaultKeyboardShortcuts(); - lcLoadDefaultMouseShortcuts(); +#ifdef LC_USE_QOPENGLWIDGET + if (!SaveAndExit) +#endif + { + gMainWindow = new lcMainWindow(); + lcLoadDefaultKeyboardShortcuts(); + lcLoadDefaultMouseShortcuts(); + } if (!LoadPartsLibrary(LibraryPaths, OnlyUseLibraryPaths, !SaveAndExit)) { @@ -782,7 +791,12 @@ lcStartupMode lcApplication::Initialize(QList>& LibraryPath fprintf(stderr, "%s", Message.toLatin1().constData()); } - gMainWindow->CreateWidgets(); +#ifdef LC_USE_QOPENGLWIDGET + if (!SaveAndExit) +#endif + { + gMainWindow->CreateWidgets(); + } Project* NewProject = new Project(); SetProject(NewProject); @@ -790,67 +804,119 @@ lcStartupMode lcApplication::Initialize(QList>& LibraryPath if (!SaveAndExit && ProjectName.isEmpty() && lcGetProfileInt(LC_PROFILE_AUTOLOAD_MOSTRECENT)) ProjectName = lcGetProfileString(LC_PROFILE_RECENT_FILE1); - if (!ProjectName.isEmpty() && gMainWindow->OpenProject(ProjectName)) + bool ProjectLoaded = false; + + if (!ProjectName.isEmpty()) + { + if (gMainWindow) + gMainWindow->OpenProject(ProjectName); + else + { + Project* LoadedProject = new Project(); + + if (LoadedProject->Load(ProjectName)) + { + SetProject(LoadedProject); + ProjectLoaded = true; + } + else + { + delete LoadedProject; + } + } + } + + if (ProjectLoaded) { if (!ModelName.isEmpty()) mProject->SetActiveModel(ModelName); +#ifdef LC_USE_QOPENGLWIDGET + std::unique_ptr ActiveView; + + if (SaveImage) + { + lcModel* Model; + + if (!ModelName.isEmpty()) + { + Model = mProject->GetModel(ModelName); + + if (!Model) + { + printf("Error: model '%s' does not exist.\n", ModelName.toLatin1().constData()); + return lcStartupMode::Error; + } + } + else + Model = mProject->GetMainModel(); + + ActiveView = std::unique_ptr(new lcView(lcViewType::View, Model)); + + ActiveView->SetOffscreenContext(); + ActiveView->MakeCurrent(); + } +#else lcView* ActiveView = gMainWindow->GetActiveView(); +#endif if (SaveImage) ActiveView->SetSize(ImageWidth, ImageHeight); - if (!CameraName.isEmpty()) + if (ActiveView) { - ActiveView->SetCamera(CameraName); - - if (Viewpoint != lcViewpoint::Count) - printf("Warning: --viewpoint is ignored when --camera is set.\n"); - - if (Orthographic) - printf("Warning: --orthographic is ignored when --camera is set.\n"); - - if (SetCameraAngles) - printf("Warning: --camera-angles is ignored when --camera is set.\n"); - - if (SetCameraPosition) - printf("Warning: --camera-position is ignored when --camera is set.\n"); - } - else - { - ActiveView->SetProjection(Orthographic); - - if (SetFoV) - ActiveView->GetCamera()->m_fovy = FoV; - - if (SetZPlanes) + if (!CameraName.isEmpty()) { - lcCamera* Camera = ActiveView->GetCamera(); + ActiveView->SetCamera(CameraName); - Camera->m_zNear = ZPlanes[0]; - Camera->m_zFar = ZPlanes[1]; - } + if (Viewpoint != lcViewpoint::Count) + printf("Warning: --viewpoint is ignored when --camera is set.\n"); - if (Viewpoint != lcViewpoint::Count) - { - ActiveView->SetViewpoint(Viewpoint); + if (Orthographic) + printf("Warning: --orthographic is ignored when --camera is set.\n"); if (SetCameraAngles) - printf("Warning: --camera-angles is ignored when --viewpoint is set.\n"); + printf("Warning: --camera-angles is ignored when --camera is set.\n"); if (SetCameraPosition) - printf("Warning: --camera-position is ignored when --viewpoint is set.\n"); + printf("Warning: --camera-position is ignored when --camera is set.\n"); } - else if (SetCameraAngles) + else { - ActiveView->SetCameraAngles(CameraLatLon[0], CameraLatLon[1]); + ActiveView->SetProjection(Orthographic); - if (SetCameraPosition) - printf("Warning: --camera-position is ignored when --camera-angles is set.\n"); - } - else if (SetCameraPosition) - { - ActiveView->SetViewpoint(CameraPosition[0], CameraPosition[1], CameraPosition[2]); + if (SetFoV) + ActiveView->GetCamera()->m_fovy = FoV; + + if (SetZPlanes) + { + lcCamera* Camera = ActiveView->GetCamera(); + + Camera->m_zNear = ZPlanes[0]; + Camera->m_zFar = ZPlanes[1]; + } + + if (Viewpoint != lcViewpoint::Count) + { + ActiveView->SetViewpoint(Viewpoint); + + if (SetCameraAngles) + printf("Warning: --camera-angles is ignored when --viewpoint is set.\n"); + + if (SetCameraPosition) + printf("Warning: --camera-position is ignored when --viewpoint is set.\n"); + } + else if (SetCameraAngles) + { + ActiveView->SetCameraAngles(CameraLatLon[0], CameraLatLon[1]); + + if (SetCameraPosition) + printf("Warning: --camera-position is ignored when --camera-angles is set.\n"); + } + else if (SetCameraPosition) + { + ActiveView->SetViewpoint(CameraPosition[0], CameraPosition[1], CameraPosition[2]); + } } } @@ -858,10 +924,14 @@ lcStartupMode lcApplication::Initialize(QList>& LibraryPath { lcModel* ActiveModel; +#ifdef LC_USE_QOPENGLWIDGET + ActiveModel = ActiveView->GetModel(); +#else if (ModelName.isEmpty()) ActiveModel = mProject->GetMainModel(); else ActiveModel = mProject->GetActiveModel(); +#endif if (ImageName.isEmpty()) ImageName = mProject->GetImageFileName(true); @@ -901,7 +971,14 @@ lcStartupMode lcApplication::Initialize(QList>& LibraryPath if (SetHighlightColor) mPreferences.mHighlightNewPartsColor = HighlightColor; +#ifdef LC_USE_QOPENGLWIDGET + if (CameraName.isEmpty() && !SetCameraPosition) + ActiveView->ZoomExtents(); + + ActiveView->SaveStepImages(Frame, ImageStart != ImageEnd, ImageStart, ImageEnd); +#else ActiveModel->SaveStepImages(Frame, ImageStart != ImageEnd, CameraName.isEmpty() && !SetCameraPosition, ImageWidth, ImageHeight, ImageStart, ImageEnd); +#endif } if (SaveWavefront) diff --git a/common/lc_global.h b/common/lc_global.h index 3be31534..2f47dfc7 100644 --- a/common/lc_global.h +++ b/common/lc_global.h @@ -48,6 +48,9 @@ #define LC_MAXPATH 1024 #define LC_MAXNAME 1000 +typedef quint32 lcStep; +#define LC_STEP_MAX 0xffffffff + #ifdef Q_OS_WIN char* strcasestr(const char *s, const char *find); #else @@ -74,6 +77,8 @@ struct lcModelPartsEntry; struct lcMinifig; enum class lcViewpoint; class lcInstructions; +struct lcObjectRayTest; +struct lcObjectBoxTest; class lcVector2; class lcVector3; diff --git a/common/lc_instructions.h b/common/lc_instructions.h index cf0aaee2..6056fd26 100644 --- a/common/lc_instructions.h +++ b/common/lc_instructions.h @@ -1,7 +1,5 @@ #pragma once -#include "object.h" - enum class lcInstructionsDirection { Horizontal, diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 5166d5bb..61be624b 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -4221,9 +4221,9 @@ void lcModel::ZoomExtents(lcCamera* Camera, float Aspect) lcVector3 Center = (Min + Max) / 2.0f; - Camera->ZoomExtents(Aspect, Center, Points, mCurrentStep, mIsPreview ? false : gMainWindow->GetAddKeys()); + Camera->ZoomExtents(Aspect, Center, Points, mCurrentStep, gMainWindow ? gMainWindow->GetAddKeys() : false); - if (!mIsPreview) + if (!mIsPreview && gMainWindow) gMainWindow->UpdateSelectedObjects(false); UpdateAllViews(); @@ -4445,6 +4445,9 @@ void lcModel::SetMinifig(const lcMinifig& Minifig) void lcModel::UpdateInterface() { + if (!gMainWindow) + return; + gMainWindow->UpdateTimeline(true, false); gMainWindow->UpdateUndoRedo(mUndoHistory.size() > 1 ? mUndoHistory[0]->Description : nullptr, !mRedoHistory.empty() ? mRedoHistory[0]->Description : nullptr); gMainWindow->UpdatePaste(!gApplication->mClipboard.isEmpty()); diff --git a/common/lc_model.h b/common/lc_model.h index 7d94893d..80e9c2fc 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -1,8 +1,8 @@ #pragma once #include "lc_math.h" -#include "object.h" #include "lc_commands.h" +#include "lc_array.h" #define LC_SEL_NO_PIECES 0x0001 // No pieces in model #define LC_SEL_PIECE 0x0002 // At last 1 piece selected @@ -92,7 +92,12 @@ public: return mSavedHistory != mUndoHistory[0]; } - bool IsPreview() + bool IsActive() const + { + return mActive; + } + + bool IsPreview() const { return mIsPreview; } diff --git a/common/lc_view.cpp b/common/lc_view.cpp index 0be58821..06dc961d 100644 --- a/common/lc_view.cpp +++ b/common/lc_view.cpp @@ -31,7 +31,8 @@ lcView::lcView(lcViewType ViewType, lcModel* Model) mDragState = lcDragState::None; mTrackToolFromOverlay = false; - lcView* ActiveView = gMainWindow->GetActiveView(); + lcView* ActiveView = gMainWindow ? gMainWindow->GetActiveView() : nullptr; + if (ActiveView) SetCamera(ActiveView->mCamera, false); else @@ -729,6 +730,67 @@ lcArray lcView::FindObjectsInBox(float x1, float y1, float x2, float return ObjectBoxTest.Objects; } +#ifdef LC_USE_QOPENGLWIDGET + +std::vector lcView::GetStepImages(lcStep Start, lcStep End) +{ + std::vector Images; + + if (!BeginRenderToImage(mWidth, mHeight)) + { + QMessageBox::warning(gMainWindow, tr("LeoCAD"), tr("Error creating images.")); + return Images; + } + + const lcStep CurrentStep = mModel->GetCurrentStep(); + + for (lcStep Step = Start; Step <= End; Step++) + { + mModel->SetTemporaryStep(Step); + + OnDraw(); + + Images.emplace_back(GetRenderImage()); + } + + EndRenderToImage(); + + mModel->SetTemporaryStep(CurrentStep); + + if (!mModel->IsActive()) + mModel->CalculateStep(LC_STEP_MAX); + + return Images; +} + +void lcView::SaveStepImages(const QString& BaseName, bool AddStepSuffix, lcStep Start, lcStep End) +{ + std::vector Images = GetStepImages(Start, End); + + for (lcStep Step = Start; Step <= End; Step++) + { + QString FileName; + + if (AddStepSuffix) + FileName = BaseName.arg(Step, 2, 10, QLatin1Char('0')); + else + FileName = BaseName; + + QImageWriter Writer(FileName); + + if (Writer.format().isEmpty()) + Writer.setFormat("png"); + + if (!Writer.write(Images[Step - Start])) + { + QMessageBox::information(gMainWindow, tr("Error"), tr("Error writing to file '%1':\n%2").arg(FileName, Writer.errorString())); + break; + } + } +} + +#endif + bool lcView::BeginRenderToImage(int Width, int Height) { GLint MaxTexture; @@ -2190,7 +2252,8 @@ void lcView::SetProjection(bool Ortho) mCamera->SetOrtho(Ortho); Redraw(); - gMainWindow->UpdatePerspective(); + if (gMainWindow) + gMainWindow->UpdatePerspective(); } else { diff --git a/common/lc_view.h b/common/lc_view.h index c1173f6c..0114f63e 100644 --- a/common/lc_view.h +++ b/common/lc_view.h @@ -244,6 +244,8 @@ public: void BindRenderFramebuffer(); void UnbindRenderFramebuffer(); QImage GetRenderFramebufferImage() const; + std::vector GetStepImages(lcStep Start, lcStep End); + void SaveStepImages(const QString& BaseName, bool AddStepSuffix, lcStep Start, lcStep End); #endif lcContext* mContext = nullptr; diff --git a/common/object.h b/common/object.h index 85a2115e..12e46674 100644 --- a/common/object.h +++ b/common/object.h @@ -3,9 +3,6 @@ #include "lc_math.h" #include "lc_array.h" -typedef quint32 lcStep; -#define LC_STEP_MAX 0xffffffff - enum class lcObjectType { Piece, diff --git a/common/project.cpp b/common/project.cpp index c0dfde95..d01d236d 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -152,7 +152,9 @@ void Project::SetActiveModel(int ModelIndex) mModels[ModelIdx]->UpdatePieceInfo(UpdatedModels); mActiveModel = mModels[ModelIndex]; - if (!mIsPreview) { + + if (!mIsPreview && gMainWindow) + { gMainWindow->SetCurrentModelTab(mActiveModel); mActiveModel->UpdateInterface(); } diff --git a/common/project.h b/common/project.h index 2876598b..1ceaa794 100644 --- a/common/project.h +++ b/common/project.h @@ -1,6 +1,5 @@ #pragma once -#include "object.h" #include "lc_array.h" #include "lc_application.h"