1 #pragma once
2 
3 #include "lc_math.h"
4 #include "lc_commands.h"
5 #include "lc_array.h"
6 
7 #define LC_SEL_NO_PIECES                0x0001 // No pieces in model
8 #define LC_SEL_PIECE                    0x0002 // At last 1 piece selected
9 #define LC_SEL_SELECTED                 0x0004 // At last 1 object selected
10 #define LC_SEL_UNSELECTED               0x0008 // At least 1 piece unselected
11 #define LC_SEL_HIDDEN                   0x0010 // At least one piece hidden
12 #define LC_SEL_HIDDEN_SELECTED          0x0020 // At least one piece selected is hidden
13 #define LC_SEL_VISIBLE_SELECTED         0x0040 // At least one piece selected is not hidden
14 #define LC_SEL_GROUPED                  0x0080 // At least one piece selected is grouped
15 #define LC_SEL_FOCUS_GROUPED            0x0100 // Focused piece is grouped
16 #define LC_SEL_CAN_GROUP                0x0200 // Can make a new group
17 #define LC_SEL_MODEL_SELECTED           0x0400 // At least one model reference is selected
18 #define LC_SEL_CAN_ADD_CONTROL_POINT    0x0800 // Can add control points to focused piece
19 #define LC_SEL_CAN_REMOVE_CONTROL_POINT 0x1000 // Can remove control points from focused piece
20 
21 enum class lcSelectionMode
22 {
23 	Single,
24 	Piece,
25 	Color,
26 	PieceColor
27 };
28 
29 enum class lcTransformType
30 {
31 	First,
32 	AbsoluteTranslation = First,
33 	RelativeTranslation,
34 	AbsoluteRotation,
35 	RelativeRotation,
36 	Count
37 };
38 
39 class lcModelProperties
40 {
41 public:
42 	void LoadDefaults();
43 	void SaveDefaults();
44 
45 	bool operator==(const lcModelProperties& Properties) const
46 	{
47 		if (mFileName != Properties.mFileName || mModelName != Properties.mModelName || mAuthor != Properties.mAuthor ||
48 			mDescription != Properties.mDescription || mComments != Properties.mComments)
49 			return false;
50 
51 		if (mAmbientColor != Properties.mAmbientColor)
52 			return false;
53 
54 		return true;
55 	}
56 
57 	void SaveLDraw(QTextStream& Stream) const;
58 	bool ParseLDrawHeader(QString Line, bool FirstLine);
59 	void ParseLDrawLine(QTextStream& Stream);
60 
61 	QString mFileName;
62 	QString mDescription;
63 	QString mModelName;
64 	QString mAuthor;
65 	QString mComments;
66 
67 	lcVector3 mAmbientColor;
68 };
69 
70 struct lcModelHistoryEntry
71 {
72 	QByteArray File;
73 	QString Description;
74 };
75 
76 class lcModel
77 {
78 public:
79 	lcModel(const QString& FileName, Project* Project, bool Preview);
80 	~lcModel();
81 
82 	lcModel(const lcModel&) = delete;
83 	lcModel& operator=(const lcModel&) = delete;
84 
GetProject()85 	Project* GetProject() const
86 	{
87 		return mProject;
88 	}
89 
IsModified()90 	bool IsModified() const
91 	{
92 		return mSavedHistory != mUndoHistory[0];
93 	}
94 
IsActive()95 	bool IsActive() const
96 	{
97 		return mActive;
98 	}
99 
100 	bool GetPieceWorldMatrix(lcPiece* Piece, lcMatrix44& ParentWorldMatrix) const;
101 	bool IncludesModel(const lcModel* Model) const;
102 	void CreatePieceInfo(Project* Project);
103 	void UpdatePieceInfo(std::vector<lcModel*>& UpdatedModels);
104 	void UpdateMesh();
105 	void UpdateAllViews() const;
106 
GetPieceInfo()107 	PieceInfo* GetPieceInfo() const
108 	{
109 		return mPieceInfo;
110 	}
111 
GetPieces()112 	const lcArray<lcPiece*>& GetPieces() const
113 	{
114 		return mPieces;
115 	}
116 
GetCameras()117 	const lcArray<lcCamera*>& GetCameras() const
118 	{
119 		return mCameras;
120 	}
121 
GetLights()122 	const lcArray<lcLight*>& GetLights() const
123 	{
124 		return mLights;
125 	}
126 
GetGroups()127 	const lcArray<lcGroup*>& GetGroups() const
128 	{
129 		return mGroups;
130 	}
131 
GetProperties()132 	const lcModelProperties& GetProperties() const
133 	{
134 		return mProperties;
135 	}
136 
SetFileName(const QString & FileName)137 	void SetFileName(const QString& FileName)
138 	{
139 		if (mProperties.mModelName == mProperties.mFileName)
140 			mProperties.mModelName = FileName;
141 		mProperties.mFileName = FileName;
142 	}
143 
GetFileName()144 	const QString& GetFileName() const
145 	{
146 		return mProperties.mFileName;
147 	}
148 
SetDescription(const QString & Description)149 	void SetDescription(const QString& Description)
150 	{
151 		mProperties.mDescription = Description;
152 	}
153 
GetFileLines()154 	const QStringList& GetFileLines() const
155 	{
156 		return mFileLines;
157 	}
158 
159 	lcStep GetLastStep() const;
160 
GetCurrentStep()161 	lcStep GetCurrentStep() const
162 	{
163 		return mCurrentStep;
164 	}
165 
166 	void SetActive(bool Active);
167 	void CalculateStep(lcStep Step);
168 	void SetCurrentStep(lcStep Step);
SetTemporaryStep(lcStep Step)169 	void SetTemporaryStep(lcStep Step)
170 	{
171 		mCurrentStep = Step;
172 		CalculateStep(Step);
173 	}
174 
175 	void ShowFirstStep();
176 	void ShowLastStep();
177 	void ShowPreviousStep();
178 	void ShowNextStep();
179 	void InsertStep(lcStep Step);
180 	void RemoveStep(lcStep Step);
181 
182 	void AddPiece();
183 	void DeleteAllCameras();
184 	void DeleteSelectedObjects();
185 	void ResetSelectedPiecesPivotPoint();
186 	void RemoveSelectedPiecesKeyFrames();
187 	void InsertControlPoint();
188 	void RemoveFocusedControlPoint();
189 	void ShowSelectedPiecesEarlier();
190 	void ShowSelectedPiecesLater();
191 	void SetPieceSteps(const QList<QPair<lcPiece*, lcStep>>& PieceSteps);
192 	void RenamePiece(PieceInfo* Info);
193 
194 	void MoveSelectionToModel(lcModel* Model);
195 	void InlineSelectedModels();
196 
197 	lcGroup* AddGroup(const QString& Prefix, lcGroup* Parent);
198 	lcGroup* GetGroup(const QString& Name, bool CreateIfMissing);
199 	void RemoveGroup(lcGroup* Group);
200 	void GroupSelection();
201 	void UngroupSelection();
202 	void AddSelectedPiecesToGroup();
203 	void RemoveFocusPieceFromGroup();
204 	void ShowEditGroupsDialog();
205 
206 	void SaveLDraw(QTextStream& Stream, bool SelectedOnly) const;
207 	void LoadLDraw(QIODevice& Device, Project* Project);
208 	bool LoadBinary(lcFile* File);
209 	bool LoadLDD(const QString& FileData);
210 	bool LoadInventory(const QByteArray& Inventory);
211 	int SplitMPD(QIODevice& Device);
212 	void Merge(lcModel* Other);
213 
SetSaved()214 	void SetSaved()
215 	{
216 		if (mUndoHistory.empty())
217 			SaveCheckpoint(QString());
218 
219 		if (!mIsPreview)
220 			mSavedHistory = mUndoHistory[0];
221 	}
222 
223 	void SetMinifig(const lcMinifig& Minifig);
224 	void SetPreviewPieceInfo(PieceInfo* Info, int ColorIndex);
225 
226 	void Cut();
227 	void Copy();
228 	void Paste(bool PasteToCurrentStep);
229 	void DuplicateSelectedPieces();
230 	void PaintSelectedPieces();
231 
232 	void GetScene(lcScene* Scene, lcCamera* ViewCamera, bool AllowHighlight, bool AllowFade) const;
233 	void AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const;
234 	QImage GetStepImage(bool Zoom, int Width, int Height, lcStep Step);
235 	QImage GetPartsListImage(int MaxWidth, lcStep Step, quint32 BackgroundColor, QFont Font, QColor TextColor) const;
236 	void SaveStepImages(const QString& BaseName, bool AddStepSuffix, bool Zoom, int Width, int Height, lcStep Start, lcStep End);
237 
238 	void RayTest(lcObjectRayTest& ObjectRayTest) const;
239 	void BoxTest(lcObjectBoxTest& ObjectBoxTest) const;
240 	bool SubModelMinIntersectDist(const lcVector3& WorldStart, const lcVector3& WorldEnd, float& MinDistance) const;
241 	bool SubModelBoxTest(const lcVector4 Planes[6]) const;
242 	void SubModelCompareBoundingBox(const lcMatrix44& WorldMatrix, lcVector3& Min, lcVector3& Max) const;
243 	void SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::vector<lcVector3>& Points) const;
244 
HasPieces()245 	bool HasPieces() const
246 	{
247 		return !mPieces.IsEmpty();
248 	}
249 
250 	bool AnyPiecesSelected() const;
251 	bool AnyObjectsSelected() const;
252 	lcModel* GetFirstSelectedSubmodel() const;
253 	void GetSubModels(lcArray<lcModel*>& SubModels) const;
254 	bool GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRotation) const;
255 	bool GetPieceFocusOrSelectionCenter(lcVector3& Center) const;
256 	lcVector3 GetSelectionOrModelCenter() const;
257 	bool GetFocusPosition(lcVector3& Position) const;
258 	lcObject* GetFocusObject() const;
259 	bool GetSelectionCenter(lcVector3& Center) const;
260 	lcBoundingBox GetAllPiecesBoundingBox() const;
261 	bool GetVisiblePiecesBoundingBox(lcVector3& Min, lcVector3& Max) const;
262 	std::vector<lcVector3> GetPiecesBoundingBoxPoints() const;
263 	void GetPartsList(int DefaultColorIndex, bool ScanSubModels, bool AddSubModels, lcPartsList& PartsList) const;
264 	void GetPartsListForStep(lcStep Step, int DefaultColorIndex, lcPartsList& PartsList) const;
265 	void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, std::vector<lcModelPartsEntry>& ModelParts) const;
266 	void GetSelectionInformation(int* Flags, lcArray<lcObject*>& Selection, lcObject** Focus) const;
267 	lcArray<lcObject*> GetSelectionModePieces(lcPiece* SelectedPiece) const;
268 
269 	void FocusOrDeselectObject(const lcObjectSection& ObjectSection);
270 	void ClearSelection(bool UpdateInterface);
271 	void ClearSelectionAndSetFocus(lcObject* Object, quint32 Section, bool EnableSelectionMode);
272 	void ClearSelectionAndSetFocus(const lcObjectSection& ObjectSection, bool EnableSelectionMode);
273 	void SetSelectionAndFocus(const lcArray<lcObject*>& Selection, lcObject* Focus, quint32 Section, bool EnableSelectionMode);
274 	void AddToSelection(const lcArray<lcObject*>& Objects, bool EnableSelectionMode, bool UpdateInterface);
275 	void RemoveFromSelection(const lcArray<lcObject*>& Objects);
276 	void RemoveFromSelection(const lcObjectSection& ObjectSection);
277 	void SelectAllPieces();
278 	void InvertSelection();
279 
280 	void HideSelectedPieces();
281 	void HideUnselectedPieces();
282 	void UnhideSelectedPieces();
283 	void UnhideAllPieces();
284 
285 	void FindReplacePiece(bool SearchForward, bool FindAll);
286 
287 	void UndoAction();
288 	void RedoAction();
289 
290 	lcVector3 SnapPosition(const lcVector3& Delta) const;
291 	lcVector3 SnapRotation(const lcVector3& Delta) const;
292 	lcMatrix33 GetRelativeRotation() const;
293 
GetMouseToolDistance()294 	const lcVector3& GetMouseToolDistance() const
295 	{
296 		return mMouseToolDistance;
297 	}
298 
299 	void BeginMouseTool();
300 	void EndMouseTool(lcTool Tool, bool Accept);
301 	void InsertPieceToolClicked(const lcMatrix44& WorldMatrix);
302 	void PointLightToolClicked(const lcVector3& Position);
303 	void BeginSpotLightTool(const lcVector3& Position, const lcVector3& Target);
304 	void UpdateSpotLightTool(const lcVector3& Position);
305 	void BeginCameraTool(const lcVector3& Position, const lcVector3& Target);
306 	void UpdateCameraTool(const lcVector3& Position);
307 	void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag);
308 	void UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag);
309 	void UpdateScaleTool(const float Scale);
310 	void EraserToolClicked(lcObject* Object);
311 	void PaintToolClicked(lcObject* Object);
312 	void ColorPickerToolClicked(lcObject* Object);
313 	void UpdateZoomTool(lcCamera* Camera, float Mouse);
314 	void UpdatePanTool(lcCamera* Camera, const lcVector3& Distance);
315 	void UpdateOrbitTool(lcCamera* Camera, float MouseX, float MouseY);
316 	void UpdateRollTool(lcCamera* Camera, float Mouse);
317 	void ZoomRegionToolClicked(lcCamera* Camera, float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners);
318 	void LookAt(lcCamera* Camera);
319 	void MoveCamera(lcCamera* Camera, const lcVector3& Direction);
320 	void ZoomExtents(lcCamera* Camera, float Aspect);
321 	void Zoom(lcCamera* Camera, float Amount);
322 
MoveSelectedObjects(const lcVector3 & Distance,bool AllowRelative,bool AlternateButtonDrag,bool Update,bool Checkpoint)323 	void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint)
324 	{
325 		MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Update, Checkpoint);
326 	}
327 
328 	void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint);
329 	void RotateSelectedPieces(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint);
330 	void ScaleSelectedPieces(const float Scale, bool Update, bool Checkpoint);
331 	void TransformSelectedObjects(lcTransformType TransformType, const lcVector3& Transform);
332 	void SetSelectedPiecesColorIndex(int ColorIndex);
333 	void SetSelectedPiecesPieceInfo(PieceInfo* Info);
334 	void SetSelectedPiecesStepShow(lcStep Step);
335 	void SetSelectedPiecesStepHide(lcStep Step);
336 
337 	void SetCameraOrthographic(lcCamera* Camera, bool Ortho);
338 	void SetCameraFOV(lcCamera* Camera, float FOV);
339 	void SetCameraZNear(lcCamera* Camera, float ZNear);
340 	void SetCameraZFar(lcCamera* Camera, float ZFar);
341 	void SetCameraName(lcCamera* Camera, const QString& Name);
342 
343 	void ShowPropertiesDialog();
344 	void ShowSelectByNameDialog();
345 	void ShowArrayDialog();
346 	void ShowMinifigDialog();
347 	void UpdateInterface();
348 
349 protected:
350 	void DeleteModel();
351 	void DeleteHistory();
352 	void SaveCheckpoint(const QString& Description);
353 	void LoadCheckPoint(lcModelHistoryEntry* CheckPoint);
354 
355 	QString GetGroupName(const QString& Prefix);
356 	void RemoveEmptyGroups();
357 	bool RemoveSelectedObjects();
358 
359 	void SelectGroup(lcGroup* TopGroup, bool Select);
360 
361 	void AddPiece(lcPiece* Piece);
362 	void InsertPiece(lcPiece* Piece, int Index);
363 
364 	lcModelProperties mProperties;
365 	Project* const mProject;
366 	PieceInfo* mPieceInfo;
367 
368 	bool mIsPreview;
369 	bool mActive;
370 	lcStep mCurrentStep;
371 	lcVector3 mMouseToolDistance;
372 
373 	lcArray<lcPiece*> mPieces;
374 	lcArray<lcCamera*> mCameras;
375 	lcArray<lcLight*> mLights;
376 	lcArray<lcGroup*> mGroups;
377 	QStringList mFileLines;
378 
379 	lcModelHistoryEntry* mSavedHistory;
380 	std::vector<lcModelHistoryEntry*> mUndoHistory;
381 	std::vector<lcModelHistoryEntry*> mRedoHistory;
382 
383 	Q_DECLARE_TR_FUNCTIONS(lcModel);
384 };
385