1 #pragma once
2 
3 class PieceInfo;
4 
5 #include "object.h"
6 #include "lc_colors.h"
7 #include "lc_math.h"
8 
9 #define LC_PIECE_HIDDEN                    0x000001
10 #define LC_PIECE_PIVOT_POINT_VALID         0x000002
11 #define LC_PIECE_POSITION_SELECTED         0x000004
12 #define LC_PIECE_POSITION_FOCUSED          0x000008
13 #define LC_PIECE_CONTROL_POINT_1_SELECTED  0x000010
14 #define LC_PIECE_CONTROL_POINT_1_FOCUSED   0x000020
15 #define LC_PIECE_CONTROL_POINT_2_SELECTED  0x000040
16 #define LC_PIECE_CONTROL_POINT_2_FOCUSED   0x000080
17 #define LC_PIECE_CONTROL_POINT_3_SELECTED  0x000100
18 #define LC_PIECE_CONTROL_POINT_3_FOCUSED   0x000200
19 #define LC_PIECE_CONTROL_POINT_4_SELECTED  0x000400
20 #define LC_PIECE_CONTROL_POINT_4_FOCUSED   0x000800
21 #define LC_PIECE_CONTROL_POINT_5_SELECTED  0x001000
22 #define LC_PIECE_CONTROL_POINT_5_FOCUSED   0x002000
23 #define LC_PIECE_CONTROL_POINT_6_SELECTED  0x004000
24 #define LC_PIECE_CONTROL_POINT_6_FOCUSED   0x008000
25 #define LC_PIECE_CONTROL_POINT_7_SELECTED  0x010000
26 #define LC_PIECE_CONTROL_POINT_7_FOCUSED   0x020000
27 #define LC_PIECE_CONTROL_POINT_8_SELECTED  0x040000
28 #define LC_PIECE_CONTROL_POINT_8_FOCUSED   0x080000
29 #define LC_PIECE_CONTROL_POINT_9_SELECTED  0x100000
30 #define LC_PIECE_CONTROL_POINT_9_FOCUSED   0x200000
31 #define LC_PIECE_CONTROL_POINT_10_SELECTED 0x400000
32 #define LC_PIECE_CONTROL_POINT_10_FOCUSED  0x800000
33 
34 #define LC_MAX_CONTROL_POINTS 10
35 
36 #define LC_PIECE_CONTROL_POINT_SELECTION_MASK (LC_PIECE_CONTROL_POINT_1_SELECTED | LC_PIECE_CONTROL_POINT_2_SELECTED | LC_PIECE_CONTROL_POINT_3_SELECTED | LC_PIECE_CONTROL_POINT_4_SELECTED | LC_PIECE_CONTROL_POINT_5_SELECTED | LC_PIECE_CONTROL_POINT_6_SELECTED | LC_PIECE_CONTROL_POINT_7_SELECTED | LC_PIECE_CONTROL_POINT_8_SELECTED | LC_PIECE_CONTROL_POINT_9_SELECTED | LC_PIECE_CONTROL_POINT_10_SELECTED)
37 #define LC_PIECE_CONTROL_POINT_FOCUS_MASK (LC_PIECE_CONTROL_POINT_1_FOCUSED | LC_PIECE_CONTROL_POINT_2_FOCUSED | LC_PIECE_CONTROL_POINT_3_FOCUSED | LC_PIECE_CONTROL_POINT_4_FOCUSED | LC_PIECE_CONTROL_POINT_5_FOCUSED | LC_PIECE_CONTROL_POINT_6_FOCUSED | LC_PIECE_CONTROL_POINT_7_FOCUSED | LC_PIECE_CONTROL_POINT_8_FOCUSED | LC_PIECE_CONTROL_POINT_9_FOCUSED | LC_PIECE_CONTROL_POINT_10_FOCUSED)
38 
39 #define LC_PIECE_SELECTION_MASK     (LC_PIECE_POSITION_SELECTED | LC_PIECE_CONTROL_POINT_SELECTION_MASK)
40 #define LC_PIECE_FOCUS_MASK         (LC_PIECE_POSITION_FOCUSED | LC_PIECE_CONTROL_POINT_FOCUS_MASK)
41 
42 enum lcPieceSection
43 {
44 	LC_PIECE_SECTION_POSITION,
45 	LC_PIECE_SECTION_CONTROL_POINT_FIRST,
46 	LC_PIECE_SECTION_CONTROL_POINT_1 = LC_PIECE_SECTION_CONTROL_POINT_FIRST,
47 	LC_PIECE_SECTION_CONTROL_POINT_2,
48 	LC_PIECE_SECTION_CONTROL_POINT_3,
49 	LC_PIECE_SECTION_CONTROL_POINT_4,
50 	LC_PIECE_SECTION_CONTROL_POINT_5,
51 	LC_PIECE_SECTION_CONTROL_POINT_6,
52 	LC_PIECE_SECTION_CONTROL_POINT_7,
53 	LC_PIECE_SECTION_CONTROL_POINT_8,
54 	LC_PIECE_SECTION_CONTROL_POINT_9,
55 	LC_PIECE_SECTION_CONTROL_POINT_10,
56 	LC_PIECE_SECTION_CONTROL_POINT_LAST = LC_PIECE_SECTION_CONTROL_POINT_10
57 };
58 
59 #define LC_PIECE_SECTION_INVALID (~0U)
60 
61 struct lcPieceControlPoint
62 {
63 	lcMatrix44 Transform;
64 	float Scale;
65 };
66 
67 class lcPiece : public lcObject
68 {
69 public:
70 	lcPiece(PieceInfo* Info);
71 	lcPiece(const lcPiece& Other);
72 	~lcPiece();
73 
74 	lcPiece(lcPiece&&) = delete;
75 	lcPiece& operator=(const lcPiece&) = delete;
76 	lcPiece& operator=(lcPiece&&) = delete;
77 
IsSelected()78 	bool IsSelected() const override
79 	{
80 		return (mState & LC_PIECE_SELECTION_MASK) != 0;
81 	}
82 
IsSelected(quint32 Section)83 	bool IsSelected(quint32 Section) const override
84 	{
85 		Q_UNUSED(Section);
86 
87 		return (mState & LC_PIECE_SELECTION_MASK) != 0;
88 	}
89 
SetSelected(bool Selected)90 	void SetSelected(bool Selected) override
91 	{
92 		if (Selected)
93 			mState |= LC_PIECE_SELECTION_MASK;
94 		else
95 			mState &= ~(LC_PIECE_SELECTION_MASK | LC_PIECE_FOCUS_MASK);
96 	}
97 
SetSelected(quint32 Section,bool Selected)98 	void SetSelected(quint32 Section, bool Selected) override
99 	{
100 		switch (Section)
101 		{
102 		case LC_PIECE_SECTION_POSITION:
103 			if (Selected)
104 				mState |= LC_PIECE_POSITION_SELECTED;
105 			else
106 				mState &= ~(LC_PIECE_POSITION_SELECTED | LC_PIECE_POSITION_FOCUSED);
107 			break;
108 
109 		case LC_PIECE_SECTION_CONTROL_POINT_1:
110 			if (Selected)
111 				mState |= LC_PIECE_CONTROL_POINT_1_SELECTED;
112 			else
113 				mState &= ~(LC_PIECE_CONTROL_POINT_1_SELECTED | LC_PIECE_CONTROL_POINT_1_FOCUSED);
114 			break;
115 
116 		case LC_PIECE_SECTION_CONTROL_POINT_2:
117 			if (Selected)
118 				mState |= LC_PIECE_CONTROL_POINT_2_SELECTED;
119 			else
120 				mState &= ~(LC_PIECE_CONTROL_POINT_2_SELECTED | LC_PIECE_CONTROL_POINT_2_FOCUSED);
121 			break;
122 
123 		case LC_PIECE_SECTION_CONTROL_POINT_3:
124 			if (Selected)
125 				mState |= LC_PIECE_CONTROL_POINT_3_SELECTED;
126 			else
127 				mState &= ~(LC_PIECE_CONTROL_POINT_3_SELECTED | LC_PIECE_CONTROL_POINT_3_FOCUSED);
128 			break;
129 
130 		case LC_PIECE_SECTION_CONTROL_POINT_4:
131 			if (Selected)
132 				mState |= LC_PIECE_CONTROL_POINT_4_SELECTED;
133 			else
134 				mState &= ~(LC_PIECE_CONTROL_POINT_4_SELECTED | LC_PIECE_CONTROL_POINT_4_FOCUSED);
135 			break;
136 
137 		case LC_PIECE_SECTION_CONTROL_POINT_5:
138 			if (Selected)
139 				mState |= LC_PIECE_CONTROL_POINT_5_SELECTED;
140 			else
141 				mState &= ~(LC_PIECE_CONTROL_POINT_5_SELECTED | LC_PIECE_CONTROL_POINT_5_FOCUSED);
142 			break;
143 
144 		case LC_PIECE_SECTION_CONTROL_POINT_6:
145 			if (Selected)
146 				mState |= LC_PIECE_CONTROL_POINT_6_SELECTED;
147 			else
148 				mState &= ~(LC_PIECE_CONTROL_POINT_6_SELECTED | LC_PIECE_CONTROL_POINT_6_FOCUSED);
149 			break;
150 
151 		case LC_PIECE_SECTION_CONTROL_POINT_7:
152 			if (Selected)
153 				mState |= LC_PIECE_CONTROL_POINT_7_SELECTED;
154 			else
155 				mState &= ~(LC_PIECE_CONTROL_POINT_7_SELECTED | LC_PIECE_CONTROL_POINT_7_FOCUSED);
156 			break;
157 
158 		case LC_PIECE_SECTION_CONTROL_POINT_8:
159 			if (Selected)
160 				mState |= LC_PIECE_CONTROL_POINT_8_SELECTED;
161 			else
162 				mState &= ~(LC_PIECE_CONTROL_POINT_8_SELECTED | LC_PIECE_CONTROL_POINT_8_FOCUSED);
163 			break;
164 
165 		case LC_PIECE_SECTION_CONTROL_POINT_9:
166 			if (Selected)
167 				mState |= LC_PIECE_CONTROL_POINT_9_SELECTED;
168 			else
169 				mState &= ~(LC_PIECE_CONTROL_POINT_9_SELECTED | LC_PIECE_CONTROL_POINT_9_FOCUSED);
170 			break;
171 
172 		case LC_PIECE_SECTION_CONTROL_POINT_10:
173 			if (Selected)
174 				mState |= LC_PIECE_CONTROL_POINT_10_SELECTED;
175 			else
176 				mState &= ~(LC_PIECE_CONTROL_POINT_10_SELECTED | LC_PIECE_CONTROL_POINT_10_FOCUSED);
177 			break;
178 		}
179 	}
180 
IsFocused()181 	bool IsFocused() const override
182 	{
183 		return (mState & LC_PIECE_FOCUS_MASK) != 0;
184 	}
185 
IsFocused(quint32 Section)186 	bool IsFocused(quint32 Section) const override
187 	{
188 		switch (Section)
189 		{
190 		case LC_PIECE_SECTION_POSITION:
191 			return (mState & LC_PIECE_POSITION_FOCUSED) != 0;
192 
193 		case LC_PIECE_SECTION_CONTROL_POINT_1:
194 			return (mState & LC_PIECE_CONTROL_POINT_1_FOCUSED) != 0;
195 
196 		case LC_PIECE_SECTION_CONTROL_POINT_2:
197 			return (mState & LC_PIECE_CONTROL_POINT_2_FOCUSED) != 0;
198 
199 		case LC_PIECE_SECTION_CONTROL_POINT_3:
200 			return (mState & LC_PIECE_CONTROL_POINT_3_FOCUSED) != 0;
201 
202 		case LC_PIECE_SECTION_CONTROL_POINT_4:
203 			return (mState & LC_PIECE_CONTROL_POINT_4_FOCUSED) != 0;
204 
205 		case LC_PIECE_SECTION_CONTROL_POINT_5:
206 			return (mState & LC_PIECE_CONTROL_POINT_5_FOCUSED) != 0;
207 
208 		case LC_PIECE_SECTION_CONTROL_POINT_6:
209 			return (mState & LC_PIECE_CONTROL_POINT_6_FOCUSED) != 0;
210 
211 		case LC_PIECE_SECTION_CONTROL_POINT_7:
212 			return (mState & LC_PIECE_CONTROL_POINT_7_FOCUSED) != 0;
213 
214 		case LC_PIECE_SECTION_CONTROL_POINT_8:
215 			return (mState & LC_PIECE_CONTROL_POINT_8_FOCUSED) != 0;
216 
217 		case LC_PIECE_SECTION_CONTROL_POINT_9:
218 			return (mState & LC_PIECE_CONTROL_POINT_9_FOCUSED) != 0;
219 
220 		case LC_PIECE_SECTION_CONTROL_POINT_10:
221 			return (mState & LC_PIECE_CONTROL_POINT_10_FOCUSED) != 0;
222 		}
223 
224 		return false;
225 	}
226 
SetFocused(quint32 Section,bool Focused)227 	void SetFocused(quint32 Section, bool Focused) override
228 	{
229 		switch (Section)
230 		{
231 		case LC_PIECE_SECTION_POSITION:
232 			if (Focused)
233 				mState |= (LC_PIECE_POSITION_SELECTED | LC_PIECE_POSITION_FOCUSED);
234 			else
235 				mState &= ~LC_PIECE_POSITION_FOCUSED;
236 			break;
237 
238 		case LC_PIECE_SECTION_CONTROL_POINT_1:
239 			if (Focused)
240 				mState |= (LC_PIECE_CONTROL_POINT_1_SELECTED | LC_PIECE_CONTROL_POINT_1_FOCUSED);
241 			else
242 				mState &= ~LC_PIECE_CONTROL_POINT_1_FOCUSED;
243 			break;
244 
245 		case LC_PIECE_SECTION_CONTROL_POINT_2:
246 			if (Focused)
247 				mState |= (LC_PIECE_CONTROL_POINT_2_SELECTED | LC_PIECE_CONTROL_POINT_2_FOCUSED);
248 			else
249 				mState &= ~LC_PIECE_CONTROL_POINT_2_FOCUSED;
250 			break;
251 
252 		case LC_PIECE_SECTION_CONTROL_POINT_3:
253 			if (Focused)
254 				mState |= (LC_PIECE_CONTROL_POINT_3_SELECTED | LC_PIECE_CONTROL_POINT_3_FOCUSED);
255 			else
256 				mState &= ~LC_PIECE_CONTROL_POINT_3_FOCUSED;
257 			break;
258 
259 		case LC_PIECE_SECTION_CONTROL_POINT_4:
260 			if (Focused)
261 				mState |= (LC_PIECE_CONTROL_POINT_4_SELECTED | LC_PIECE_CONTROL_POINT_4_FOCUSED);
262 			else
263 				mState &= ~LC_PIECE_CONTROL_POINT_4_FOCUSED;
264 			break;
265 
266 		case LC_PIECE_SECTION_CONTROL_POINT_5:
267 			if (Focused)
268 				mState |= (LC_PIECE_CONTROL_POINT_5_SELECTED | LC_PIECE_CONTROL_POINT_5_FOCUSED);
269 			else
270 				mState &= ~LC_PIECE_CONTROL_POINT_5_FOCUSED;
271 			break;
272 
273 		case LC_PIECE_SECTION_CONTROL_POINT_6:
274 			if (Focused)
275 				mState |= (LC_PIECE_CONTROL_POINT_6_SELECTED | LC_PIECE_CONTROL_POINT_6_FOCUSED);
276 			else
277 				mState &= ~LC_PIECE_CONTROL_POINT_6_FOCUSED;
278 			break;
279 
280 		case LC_PIECE_SECTION_CONTROL_POINT_7:
281 			if (Focused)
282 				mState |= (LC_PIECE_CONTROL_POINT_7_SELECTED | LC_PIECE_CONTROL_POINT_7_FOCUSED);
283 			else
284 				mState &= ~LC_PIECE_CONTROL_POINT_7_FOCUSED;
285 			break;
286 
287 		case LC_PIECE_SECTION_CONTROL_POINT_8:
288 			if (Focused)
289 				mState |= (LC_PIECE_CONTROL_POINT_8_SELECTED | LC_PIECE_CONTROL_POINT_8_FOCUSED);
290 			else
291 				mState &= ~LC_PIECE_CONTROL_POINT_8_FOCUSED;
292 			break;
293 
294 		case LC_PIECE_SECTION_CONTROL_POINT_9:
295 			if (Focused)
296 				mState |= (LC_PIECE_CONTROL_POINT_9_SELECTED | LC_PIECE_CONTROL_POINT_9_FOCUSED);
297 			else
298 				mState &= ~LC_PIECE_CONTROL_POINT_9_FOCUSED;
299 			break;
300 
301 		case LC_PIECE_SECTION_CONTROL_POINT_10:
302 			if (Focused)
303 				mState |= (LC_PIECE_CONTROL_POINT_10_SELECTED | LC_PIECE_CONTROL_POINT_10_FOCUSED);
304 			else
305 				mState &= ~LC_PIECE_CONTROL_POINT_10_FOCUSED;
306 			break;
307 		}
308 	}
309 
GetFocusSection()310 	quint32 GetFocusSection() const override
311 	{
312 		if (mState & LC_PIECE_POSITION_FOCUSED)
313 			return LC_PIECE_SECTION_POSITION;
314 
315 		if (mState & LC_PIECE_CONTROL_POINT_1_FOCUSED)
316 			return LC_PIECE_SECTION_CONTROL_POINT_1;
317 
318 		if (mState & LC_PIECE_CONTROL_POINT_2_FOCUSED)
319 			return LC_PIECE_SECTION_CONTROL_POINT_2;
320 
321 		if (mState & LC_PIECE_CONTROL_POINT_3_FOCUSED)
322 			return LC_PIECE_SECTION_CONTROL_POINT_3;
323 
324 		if (mState & LC_PIECE_CONTROL_POINT_4_FOCUSED)
325 			return LC_PIECE_SECTION_CONTROL_POINT_4;
326 
327 		if (mState & LC_PIECE_CONTROL_POINT_5_FOCUSED)
328 			return LC_PIECE_SECTION_CONTROL_POINT_5;
329 
330 		if (mState & LC_PIECE_CONTROL_POINT_6_FOCUSED)
331 			return LC_PIECE_SECTION_CONTROL_POINT_6;
332 
333 		if (mState & LC_PIECE_CONTROL_POINT_7_FOCUSED)
334 			return LC_PIECE_SECTION_CONTROL_POINT_7;
335 
336 		if (mState & LC_PIECE_CONTROL_POINT_8_FOCUSED)
337 			return LC_PIECE_SECTION_CONTROL_POINT_8;
338 
339 		if (mState & LC_PIECE_CONTROL_POINT_9_FOCUSED)
340 			return LC_PIECE_SECTION_CONTROL_POINT_9;
341 
342 		if (mState & LC_PIECE_CONTROL_POINT_10_FOCUSED)
343 			return LC_PIECE_SECTION_CONTROL_POINT_10;
344 
345 		return LC_PIECE_SECTION_INVALID;
346 	}
347 
348 	quint32 GetAllowedTransforms() const override;
349 
GetSectionPosition(quint32 Section)350 	lcVector3 GetSectionPosition(quint32 Section) const override
351 	{
352 		switch (Section)
353 		{
354 		case LC_PIECE_SECTION_POSITION:
355 			if (mState & LC_PIECE_PIVOT_POINT_VALID)
356 				return lcMul(mPivotMatrix, mModelWorld).GetTranslation();
357 			else
358 				return mModelWorld.GetTranslation();
359 
360 		case LC_PIECE_SECTION_CONTROL_POINT_1:
361 			return lcMul(mControlPoints[0].Transform, mModelWorld).GetTranslation();
362 
363 		case LC_PIECE_SECTION_CONTROL_POINT_2:
364 			return lcMul(mControlPoints[1].Transform, mModelWorld).GetTranslation();
365 
366 		case LC_PIECE_SECTION_CONTROL_POINT_3:
367 			return lcMul(mControlPoints[2].Transform, mModelWorld).GetTranslation();
368 
369 		case LC_PIECE_SECTION_CONTROL_POINT_4:
370 			return lcMul(mControlPoints[3].Transform, mModelWorld).GetTranslation();
371 
372 		case LC_PIECE_SECTION_CONTROL_POINT_5:
373 			return lcMul(mControlPoints[4].Transform, mModelWorld).GetTranslation();
374 
375 		case LC_PIECE_SECTION_CONTROL_POINT_6:
376 			return lcMul(mControlPoints[5].Transform, mModelWorld).GetTranslation();
377 
378 		case LC_PIECE_SECTION_CONTROL_POINT_7:
379 			return lcMul(mControlPoints[6].Transform, mModelWorld).GetTranslation();
380 
381 		case LC_PIECE_SECTION_CONTROL_POINT_8:
382 			return lcMul(mControlPoints[7].Transform, mModelWorld).GetTranslation();
383 
384 		case LC_PIECE_SECTION_CONTROL_POINT_9:
385 			return lcMul(mControlPoints[8].Transform, mModelWorld).GetTranslation();
386 
387 		case LC_PIECE_SECTION_CONTROL_POINT_10:
388 			return lcMul(mControlPoints[9].Transform, mModelWorld).GetTranslation();
389 		}
390 
391 		return lcVector3(0.0f, 0.0f, 0.0f);
392 	}
393 
394 	void SaveLDraw(QTextStream& Stream) const;
395 	bool ParseLDrawLine(QTextStream& Stream);
396 
SetFileLine(int Line)397 	void SetFileLine(int Line)
398 	{
399 		mFileLine = Line;
400 	}
401 
GetFileLine()402 	int GetFileLine() const
403 	{
404 		return mFileLine;
405 	}
406 
407 	void RayTest(lcObjectRayTest& ObjectRayTest) const override;
408 	void BoxTest(lcObjectBoxTest& ObjectBoxTest) const override;
409 	void DrawInterface(lcContext* Context, const lcScene& Scene) const override;
410 	void RemoveKeyFrames() override;
411 
412 	void AddMainModelRenderMeshes(lcScene* Scene, bool Highlight, bool Fade) const;
413 	void AddSubModelRenderMeshes(lcScene* Scene, const lcMatrix44& WorldMatrix, int DefaultColorIndex, lcRenderMeshState RenderMeshState, bool ParentActive) const;
414 	void SubModelCompareBoundingBox(const lcMatrix44& WorldMatrix, lcVector3& Min, lcVector3& Max) const;
415 	void SubModelAddBoundingBoxPoints(const lcMatrix44& WorldMatrix, std::vector<lcVector3>& Points) const;
416 
417 	void InsertTime(lcStep Start, lcStep Time);
418 	void RemoveTime(lcStep Start, lcStep Time);
419 
IsHidden()420 	bool IsHidden() const
421 	{
422 		return (mState & LC_PIECE_HIDDEN) != 0;
423 	}
424 
SetHidden(bool Hidden)425 	void SetHidden(bool Hidden)
426 	{
427 		if (Hidden)
428 			mState |= LC_PIECE_HIDDEN;
429 		else
430 			mState &= ~LC_PIECE_HIDDEN;
431 	}
432 
GetControlPoints()433 	const lcArray<lcPieceControlPoint>& GetControlPoints() const
434 	{
435 		return mControlPoints;
436 	}
437 
SetControlPoints(const lcArray<lcPieceControlPoint> & ControlPoints)438 	void SetControlPoints(const lcArray<lcPieceControlPoint>& ControlPoints)
439 	{
440 		mControlPoints = ControlPoints;
441 		UpdateMesh();
442 	}
443 
SetControlPointScale(int ControlPointIndex,float Scale)444 	void SetControlPointScale(int ControlPointIndex, float Scale)
445 	{
446 		mControlPoints[ControlPointIndex].Scale = Scale;
447 		UpdateMesh();
448 	}
449 
GetID()450 	const QString& GetID() const
451 	{
452 		return mID;
453 	}
454 
455 	void UpdateID();
456 
457 	QString GetName() const override;
458 	bool IsVisible(lcStep Step) const;
459 	bool IsVisibleInSubModel() const;
460 	void GetModelParts(const lcMatrix44& WorldMatrix, int DefaultColorIndex, std::vector<lcModelPartsEntry>& ModelParts) const;
461 	void Initialize(const lcMatrix44& WorldMatrix, lcStep Step);
462 	const lcBoundingBox& GetBoundingBox() const;
463 	void CompareBoundingBox(lcVector3& Min, lcVector3& Max) const;
464 	void SetPieceInfo(PieceInfo* Info, const QString& ID, bool Wait);
465 	bool FileLoad(lcFile& file);
466 
467 	void UpdatePosition(lcStep Step);
468 	void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance);
469 	void Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame);
470 	void MovePivotPoint(const lcVector3& Distance);
471 	void RotatePivotPoint(const lcMatrix33& RotationMatrix);
472 
473 	bool CanAddControlPoint() const;
474 	bool CanRemoveControlPoint() const;
475 
476 	bool InsertControlPoint(const lcVector3& WorldStart, const lcVector3& WorldEnd);
477 	bool RemoveFocusedControlPoint();
478 	void VerifyControlPoints(lcArray<lcPieceControlPoint>& ControlPoints) const;
479 
480 	lcGroup* GetTopGroup();
481 
SetGroup(lcGroup * Group)482 	void SetGroup(lcGroup* Group)
483 	{
484 		mGroup = Group;
485 	}
486 
GetGroup()487 	lcGroup* GetGroup()
488 	{
489 		return mGroup;
490 	}
491 
GetStepShow()492 	lcStep GetStepShow() const
493 	{
494 		return mStepShow;
495 	}
496 
GetStepHide()497 	lcStep GetStepHide() const
498 	{
499 		return mStepHide;
500 	}
501 
SetStepHide(lcStep Step)502 	void SetStepHide(lcStep Step)
503 	{
504 		if (Step < 2)
505 			Step = 2;
506 
507 		mStepHide = Step;
508 
509 		if (mStepHide <= mStepShow)
510 			SetStepShow(mStepHide - 1);
511 	}
512 
SetStepShow(lcStep Step)513 	void SetStepShow(lcStep Step)
514 	{
515 		if (Step == LC_STEP_MAX)
516 			Step = LC_STEP_MAX - 1;
517 
518 		if (mStepShow != Step)
519 		{
520 			mFileLine = -1;
521 			mStepShow = Step;
522 		}
523 
524 		if (mStepHide <= mStepShow)
525 			mStepHide = mStepShow + 1;
526 	}
527 
GetColorCode()528 	quint32 GetColorCode() const
529 	{
530 		return mColorCode;
531 	}
532 
SetColorCode(quint32 ColorCode)533 	void SetColorCode(quint32 ColorCode)
534 	{
535 		mColorCode = ColorCode;
536 		mColorIndex = lcGetColorIndex(ColorCode);
537 	}
538 
GetColorIndex()539 	int GetColorIndex() const
540 	{
541 		return mColorIndex;
542 	}
543 
SetColorIndex(int ColorIndex)544 	void SetColorIndex(int ColorIndex)
545 	{
546 		mColorIndex = ColorIndex;
547 		mColorCode = lcGetColorCode(ColorIndex);
548 	}
549 
SetPosition(const lcVector3 & Position,lcStep Step,bool AddKey)550 	void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey)
551 	{
552 		mPositionKeys.ChangeKey(Position, Step, AddKey);
553 	}
554 
SetRotation(const lcMatrix33 & Rotation,lcStep Step,bool AddKey)555 	void SetRotation(const lcMatrix33& Rotation, lcStep Step, bool AddKey)
556 	{
557 		mRotationKeys.ChangeKey(Rotation, Step, AddKey);
558 	}
559 
GetRotationCenter()560 	lcVector3 GetRotationCenter() const
561 	{
562 		const quint32 Section = GetFocusSection();
563 
564 		if (Section == LC_PIECE_SECTION_POSITION || Section == LC_PIECE_SECTION_INVALID)
565 		{
566 			if (mState & LC_PIECE_PIVOT_POINT_VALID)
567 				return lcMul31(mPivotMatrix.GetTranslation(), mModelWorld);
568 			else
569 				return mModelWorld.GetTranslation();
570 		}
571 		else
572 		{
573 			const int ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_1;
574 
575 			if (ControlPointIndex >= 0 && ControlPointIndex < mControlPoints.GetSize())
576 			{
577 				const lcMatrix44& Transform = mControlPoints[ControlPointIndex].Transform;
578 				return lcMul31(Transform.GetTranslation(), mModelWorld);
579 			}
580 
581 			return mModelWorld.GetTranslation();
582 		}
583 	}
584 
GetRelativeRotation()585 	lcMatrix33 GetRelativeRotation() const
586 	{
587 		const quint32 Section = GetFocusSection();
588 
589 		if (Section == LC_PIECE_SECTION_POSITION || Section == LC_PIECE_SECTION_INVALID)
590 		{
591 			if (mState & LC_PIECE_PIVOT_POINT_VALID)
592 				return lcMatrix33(lcMul(mModelWorld, mPivotMatrix));
593 			else
594 				return lcMatrix33(mModelWorld);
595 		}
596 		else
597 		{
598 			const int ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_1;
599 
600 			if (ControlPointIndex >= 0 && ControlPointIndex < mControlPoints.GetSize())
601 			{
602 				const lcMatrix44& Transform = mControlPoints[ControlPointIndex].Transform;
603 				return lcMatrix33(lcMul(Transform, mModelWorld));
604 			}
605 
606 			return lcMatrix33Identity();
607 		}
608 	}
609 
ResetPivotPoint()610 	void ResetPivotPoint()
611 	{
612 		mState &= ~LC_PIECE_PIVOT_POINT_VALID;
613 		mPivotMatrix = lcMatrix44Identity();
614 	}
615 
616 public:
617 	PieceInfo* mPieceInfo;
618 
619 	lcMatrix44 mModelWorld;
620 	lcMatrix44 mPivotMatrix;
621 
622 protected:
623 	void UpdateMesh();
624 
IsPivotPointVisible()625 	bool IsPivotPointVisible() const
626 	{
627 		return (mState & LC_PIECE_PIVOT_POINT_VALID) && IsFocused();
628 	}
629 
AreControlPointsVisible()630 	bool AreControlPointsVisible() const
631 	{
632 		return IsSelected();
633 	}
634 
635 	lcObjectKeyArray<lcVector3> mPositionKeys;
636 	lcObjectKeyArray<lcMatrix33> mRotationKeys;
637 
638 	int mFileLine;
639 	QString mID;
640 
641 	lcGroup* mGroup;
642 
643 	int mColorIndex;
644 	quint32 mColorCode;
645 
646 	lcStep mStepShow;
647 	lcStep mStepHide;
648 
649 	quint32 mState;
650 	lcArray<lcPieceControlPoint> mControlPoints;
651 	lcMesh* mMesh;
652 };
653