#pragma once #include "lc_math.h" #include "lc_commands.h" enum class lcObjectPropertyId; enum class lcCameraProjection; struct lcSetInventoryItem; struct lcModelHistoryEditState; class lcModelHistory; class lcModelHistorySelect; class lcModelHistoryEdit; class lcModelHistoryProperties; enum class lcModelHistoryEditMerge; #define LC_SEL_NO_PIECES 0x0001 // No pieces in model #define LC_SEL_PIECE 0x0002 // At least 1 piece selected #define LC_SEL_CAMERA 0x0004 // At least 1 camera selected #define LC_SEL_LIGHT 0x0008 // At least 1 light selected #define LC_SEL_SELECTED 0x0010 // At least 1 object selected #define LC_SEL_UNSELECTED 0x0020 // At least 1 piece unselected #define LC_SEL_HIDDEN 0x0040 // At least one piece hidden #define LC_SEL_HIDDEN_SELECTED 0x0080 // At least one piece selected is hidden #define LC_SEL_VISIBLE_SELECTED 0x0100 // At least one piece selected is not hidden #define LC_SEL_GROUPED 0x0200 // At least one piece selected is grouped #define LC_SEL_FOCUS_GROUPED 0x0400 // Focused piece is grouped #define LC_SEL_CAN_GROUP 0x0800 // Can make a new group #define LC_SEL_MODEL_SELECTED 0x1000 // At least one model reference is selected #define LC_SEL_CAN_ADD_CONTROL_POINT 0x2000 // Can add control points to focused piece #define LC_SEL_CAN_REMOVE_CONTROL_POINT 0x4000 // Can remove control points from focused piece #define LC_SEL_TRAIN_TRACK_VISIBLE 0x8000 // Focused piece has train track connections enum class lcSelectionMode { Single, Piece, Color, PieceColor }; enum class lcTransformType { First, AbsoluteTranslation = First, RelativeTranslation, AbsoluteRotation, RelativeRotation, Count }; struct lcInsertPieceInfo { PieceInfo* Info; lcMatrix44 Transform; int ColorIndex; }; class lcModelProperties { public: void LoadDefaults(); void SaveDefaults(); bool operator==(const lcModelProperties& Properties) const { if (mFileName != Properties.mFileName || mModelName != Properties.mModelName || mAuthor != Properties.mAuthor || mDescription != Properties.mDescription || mComments != Properties.mComments) return false; if (mAmbientColor != Properties.mAmbientColor) return false; return true; } bool operator!=(const lcModelProperties& Properties) const { return !(*this == Properties); } void SaveLDraw(QTextStream& Stream) const; bool ParseLDrawHeader(QString Line, bool FirstLine); void ParseLDrawLine(QTextStream& Stream); QString mFileName; QString mDescription; QString mModelName; QString mAuthor; QString mComments; lcVector3 mAmbientColor; }; class lcPOVRayOptions { public: void ParseLDrawLine(QTextStream& LineStream); void SaveLDraw(QTextStream& Stream) const; bool UseLGEO = false; bool ExcludeFloor = false; bool ExcludeBackground = false; bool NoReflection = false; bool NoShadow = false; int FloorAxis = 1; float FloorAmbient = 0.4f; float FloorDiffuse = 0.4f; lcVector3 FloorColor = lcVector3(0.8f,0.8f,0.8f); QString HeaderIncludeFile; QString FooterIncludeFile; }; struct lcModelHistoryEntry { std::vector> HistorySequence; QString Description; }; class lcModel { public: lcModel(const QString& FileName, Project* Project, bool Preview); ~lcModel(); lcModel(const lcModel&) = delete; lcModel(lcModel&&) = delete; lcModel& operator=(const lcModel&) = delete; lcModel& operator=(lcModel&&) = delete; Project* GetProject() const { return mProject; } bool IsActive() const { return mActive; } bool IsModified() const; void SetSaved(); bool GetPieceWorldMatrix(lcPiece* Piece, lcMatrix44& ParentWorldMatrix) const; bool IncludesModel(const lcModel* Model) const; void CreatePieceInfo(Project* Project); void UpdatePieceInfo(std::vector& UpdatedModels); void UpdateMesh(); void UpdateAllViews() const; PieceInfo* GetPieceInfo() const { return mPieceInfo; } const std::vector>& GetPieces() const { return mPieces; } const std::vector>& GetCameras() const { return mCameras; } const std::vector>& GetLights() const { return mLights; } const std::vector>& GetGroups() const { return mGroups; } const lcModelProperties& GetProperties() const { return mProperties; } const lcPOVRayOptions& GetPOVRayOptions() const { return mPOVRayOptions; } void SetFileName(const QString& FileName) { if (mProperties.mModelName == mProperties.mFileName) mProperties.mModelName = FileName; mProperties.mFileName = FileName; } const QString& GetFileName() const { return mProperties.mFileName; } void SetDescription(const QString& Description) { mProperties.mDescription = Description; } const QStringList& GetFileLines() const { return mFileLines; } lcStep GetLastStep() const; lcStep GetCurrentStep() const { return mCurrentStep; } void SetActive(bool Active); void CalculateStep(lcStep Step); void SetCurrentStep(lcStep Step); void SetTemporaryStep(lcStep Step) { mCurrentStep = Step; CalculateStep(Step); } void ShowFirstStep(); void ShowLastStep(); void ShowPreviousStep(); void ShowNextStep(); void InsertStepAction(lcStep Step); void RemoveStepAction(lcStep Step); template void LoadObjectHistoryState(const std::vector& ObjectStates, std::vector>& Objects); void LoadEditHistoryState(const lcModelHistoryEditState& HistoryState); void LoadModelPropertiesState(const lcModelProperties& ModelProperties); lcPiece* AddPiece(PieceInfo* Info, quint32 Section); void AddPiece(std::unique_ptr Piece, size_t PieceIndex); void DeleteSelectedObjects(); void ResetSelectedPiecesPivotPoint(); void RemoveSelectedObjectsKeyFrames(); void InsertControlPoint(); void RemoveFocusedControlPoint(); void FocusNextTrainTrack(); void FocusPreviousTrainTrack(); void RotateFocusedTrainTrack(int Direction); void ShowSelectedPiecesEarlier(); void ShowSelectedPiecesLater(); void InsertStepAndMoveSelectedPieces(lcStep Step); void SetPieceSteps(const std::vector>& PieceSteps); void RenamePiece(PieceInfo* Info); void MoveSelectionToModel(lcModel* Model); void InlineSelectedModels(); lcGroup* AddGroup(const QString& Prefix, lcGroup* Parent); lcGroup* GetGroup(const QString& Name, bool CreateIfMissing); void RemoveGroup(lcGroup* Group); void GroupSelection(); void UngroupSelection(); void AddSelectedPiecesToGroup(); void RemoveFocusPieceFromGroup(); void ShowEditGroupsDialog(); void SaveLDraw(QTextStream& Stream, bool SelectedOnly, lcStep LastStep) const; void LoadLDraw(QIODevice& Device, Project* Project); bool LoadBinary(lcFile* File); bool LoadLDD(const QString& FileData); bool LoadInventory(const std::vector& SetInventory); int SplitMPD(QIODevice& Device); void Merge(std::unique_ptr Other); void SetMinifig(const lcMinifig& Minifig); void SetPreviewPieceInfo(PieceInfo* Info, int ColorIndex); void Cut(); void Copy(); void Paste(bool PasteToCurrentStep); void DuplicateSelectedPieces(); void PaintSelectedPieces(); void UpdateTrainTrackConnections(lcPiece* TrackPiece, bool IgnoreSelected) const; void UpdateSelectedPiecesTrainTrackConnections(); void SetPreviewInsertPieceInfo(std::vector&& PreviewInsertPieceInfo); const std::vector& GetPreviewInsertPieceInfo() const { return mPreviewInsertPieceInfo; } void GetScene(lcScene* Scene, const lcCamera* ViewCamera, bool AllowHighlight, bool AllowFade) const; void AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const; QImage GetStepImage(bool Zoom, int Width, int Height, lcStep Step); QImage GetPartsListImage(int MaxWidth, lcStep Step, quint32 BackgroundColor, QFont Font, QColor TextColor) const; void SaveStepImages(const QString& BaseName, bool AddStepSuffix, bool Zoom, int Width, int Height, lcStep Start, lcStep End); void RayTest(lcObjectRayTest& ObjectRayTest) const; void BoxTest(lcObjectBoxTest& ObjectBoxTest) const; bool SubModelMinIntersectDist(const lcVector3& WorldStart, const lcVector3& WorldEnd, float& MinDistance, lcPieceInfoRayTest& PieceInfoRayTest) const; bool SubModelBoxTest(const lcVector4 Planes[6]) const; void SubModelCompareBoundingBox(const lcMatrix44& WorldMatrix, lcVector3& Min, lcVector3& Max) const; void SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::vector& Points) const; bool HasPieces() const { return !mPieces.empty(); } bool AnyPiecesSelected() const; bool AnyObjectsSelected() const; lcModel* GetFirstSelectedSubmodel() const; void GetSubModels(std::set& SubModels) const; bool GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRotation) const; bool CanRotateSelection() const; bool GetPieceFocusOrSelectionCenter(lcVector3& Center) const; lcVector3 GetSelectionOrModelCenter() const; bool GetFocusPosition(lcVector3& Position) const; lcObject* GetFocusObject() const; bool GetSelectionCenter(lcVector3& Center) const; lcBoundingBox GetAllPiecesBoundingBox() const; bool GetVisiblePiecesBoundingBox(lcVector3& Min, lcVector3& Max) const; std::vector GetPiecesBoundingBoxPoints() const; void GetPartsList(int DefaultColorIndex, bool ScanSubModels, bool AddSubModels, lcPartsList& PartsList) const; void GetPartsListForStep(lcStep Step, int DefaultColorIndex, lcPartsList& PartsList, bool Cumulative) const; void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, std::vector& ModelParts) const; void GetSelectionInformation(int* Flags, std::vector& Selection, lcObject** Focus) const; void ClearSelectionAction(); void SetSelectionAndFocusAction(const std::vector& Selection, lcObject* Focus, quint32 Section, lcSelectionMode SelectionMode); void FocusOrDeselectObjectAction(lcObject* Object, uint32_t Section, lcSelectionMode SelectionMode); void SelectAllPiecesAction(); void InvertPieceSelectionAction(); void AddToSelectionAction(const std::vector& Objects); void RemoveFromSelectionAction(const std::vector& Objects); void HideSelectedPieces(); void HideUnselectedPieces(); void UnhideSelectedPieces(); void UnhideAllPieces(); void FindReplacePiece(bool SearchForward, bool FindAll, bool Replace); void UndoAction(); void RedoAction(); lcVector3 SnapPosition(const lcVector3& Delta) const; lcVector3 SnapRotation(const lcVector3& Delta) const; lcMatrix33 GetRelativeRotation() const; const lcVector3& GetMouseToolDistance() const { return mMouseToolDistance; } void BeginMouseTool(lcTool Tool, lcView* View); void EndMouseTool(lcTool Tool, lcView* View, bool Accept); bool InsertPieceToolClicked(std::optional Transform); void InsertCameraToolClicked(const lcVector3& Position); void InsertLightToolClicked(const lcVector3& Position, lcLightType LightType); void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag); void UpdateFreeMoveTool(lcPiece* MousePiece, const lcMatrix44& StartTransform, const lcMatrix44& NewTransform, bool IsConnection, bool AlternateButtonDrag); void UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag); void UpdateScaleTool(const float Scale); void EraserToolClicked(lcObject* Object); void PaintToolClicked(lcObject* Object); void ColorPickerToolClicked(const lcObject* Object); void UpdateZoomTool(lcCamera* Camera, float Mouse); void UpdatePanTool(lcCamera* Camera, const lcVector3& Distance); void UpdateOrbitTool(lcCamera* Camera, float MouseX, float MouseY); void UpdateRollTool(lcCamera* Camera, float Mouse); void ZoomRegionToolClicked(lcView* View, float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners); void LookAt(lcCamera* Camera); void MoveCamera(lcCamera* Camera, const lcVector3& Direction); void ZoomExtents(lcCamera* Camera, float Aspect, const lcMatrix44& WorldMatrix); void Zoom(lcCamera* Camera, float Amount); void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove, lcModelHistoryEditMerge ModelHistoryEditMerge) { MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Checkpoint, FirstMove, ModelHistoryEditMerge); } void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Checkpoint, bool FirstMove, lcModelHistoryEditMerge ModelHistoryEditMerge); void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Checkpoint, lcModelHistoryEditMerge ModelHistoryEditMerge); void ScaleSelectedPieces(const float Scale); void TransformSelectedObjects(lcTransformType TransformType, const lcVector3& Transform); void SetObjectsKeyFrame(const std::vector& Objects, lcObjectPropertyId PropertyId, bool KeyFrame); void SetSelectedPiecesColorIndex(int ColorIndex); void SetSelectedPiecesStepShow(lcStep Step); void SetSelectedPiecesStepHide(lcStep Step); void SetObjectsProperty(const std::vector& Objects, lcObjectPropertyId PropertyId, QVariant Value); void EndPropertyEdit(lcObjectPropertyId PropertyId, bool Accept); void SetCameraProjection(lcCamera* Camera, lcCameraProjection CameraProjection); void ShowPropertiesDialog(); void ShowArrayDialog(); void ShowMinifigDialog(); void UpdateInterface(); protected: void DeleteModel(); void AddSelectionHistory(std::function Callback); void ClearSelection(); void SetFocus(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); void SetSelectionAndFocus(const std::vector& Objects, lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); void SelectAllPieces(); void InvertPieceSelection(); void AddToSelection(const std::vector& Objects); void RemoveFromSelection(const std::vector& Objects); void BeginEditHistory(lcModelHistoryEditMerge ModelHistoryEditMerge); void EndEditHistory(); void SetModelProperties(const lcModelProperties& ModelProperties); void RunHistorySequence(const std::vector>& HistorySequence, bool Apply); void BeginHistorySequence(); void EndHistorySequence(const QString& Description); void DiscardHistorySequence(); void RevertHistorySequence(); void RemoveFirstUndoIfUnchanged(); const lcModelHistoryEntry* GetFirstUndoChange() const; QString GetGroupName(const QString& Prefix); void RemoveEmptyGroups(); bool RemoveSelectedObjects(); void RemoveCameraFromViews(lcCamera* Camera); std::vector GetSelectionModePieces(lcSelectionMode SelectionMode, const lcPiece* SelectedPiece) const; void DeselectAllObjects(); void SetFocusedObject(lcObject* FocusObject, uint32_t FocusSection, lcSelectionMode SelectionMode); void SetObjectsSelected(const std::vector& Objects, bool Selected); void SelectGroup(lcGroup* TopGroup, bool Select); size_t AddPiece(lcPiece* Piece); void InsertStep(lcStep Step); lcPOVRayOptions mPOVRayOptions; lcModelProperties mProperties; Project* const mProject; PieceInfo* mPieceInfo; bool mIsPreview; bool mActive; lcStep mCurrentStep; lcVector3 mMouseToolDistance; bool mMouseToolFirstMove; std::vector mPreviewInsertPieceInfo; std::vector> mPieces; std::vector> mCameras; std::vector> mLights; std::vector> mGroups; QStringList mFileLines; std::vector> mHistorySequence; const lcModelHistoryEntry* mSavedHistory = nullptr; std::vector> mUndoHistory; std::vector> mRedoHistory; Q_DECLARE_TR_FUNCTIONS(lcModel); };