From dfc94a42e56437caa3f9dbb9e905e078106adb48 Mon Sep 17 00:00:00 2001
From: leo <leozide@users.noreply.github.com>
Date: Tue, 15 Dec 2015 01:57:22 +0000
Subject: [PATCH] Rotate pivot points.

---
 common/lc_model.cpp | 129 ++++++++++++++++++++++++--------------------
 common/piece.cpp    |  41 +++++++-------
 common/piece.h      |  10 ++--
 3 files changed, 97 insertions(+), 83 deletions(-)

diff --git a/common/lc_model.cpp b/common/lc_model.cpp
index 6a45ed53..275242e0 100644
--- a/common/lc_model.cpp
+++ b/common/lc_model.cpp
@@ -2299,38 +2299,8 @@ void lcModel::RotateSelectedPieces(const lcVector3& Angles, bool Relative, bool
 	if (Angles.LengthSquared() < 0.001f)
 		return;
 
-	float Bounds[6] = { FLT_MAX, FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX };
-	lcPiece* Focus = NULL;
-	lcPiece* Selected = NULL;
-	int NumSelected = 0;
-
-	for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
-	{
-		lcPiece* Piece = mPieces[PieceIdx];
-
-		if (Piece->IsSelected())
-		{
-			if (Piece->IsFocused())
-				Focus = Piece;
-
-			Piece->CompareBoundingBox(Bounds);
-
-			Selected = Piece;
-			NumSelected++;
-		}
-	}
-
-	lcVector3 Center;
-
-	if (Focus)
-		Center = Focus->GetRotationCenter();
-	else if (NumSelected == 1)
-		Center = Selected->GetRotationCenter();
-	else
-		Center = lcVector3((Bounds[0] + Bounds[3]) / 2.0f, (Bounds[1] + Bounds[4]) / 2.0f, (Bounds[2] + Bounds[5]) / 2.0f);
-
 	lcMatrix33 RotationMatrix = lcMatrix33Identity();
-	lcMatrix33 WorldToFocusMatrix;
+	bool Rotated = false;
 
 	if (Angles[0] != 0.0f)
 		RotationMatrix = lcMul(lcMatrix33RotationX(Angles[0] * LC_DTOR), RotationMatrix);
@@ -2341,45 +2311,88 @@ void lcModel::RotateSelectedPieces(const lcVector3& Angles, bool Relative, bool
 	if (Angles[2] != 0.0f)
 		RotationMatrix = lcMul(lcMatrix33RotationZ(Angles[2] * LC_DTOR), RotationMatrix);
 
-	if (!gMainWindow->GetRelativeTransform())
-		Focus = NULL;
-
-	if (Focus && Relative)
+	if (AlternateButtonDrag)
 	{
-		lcMatrix33 FocusToWorldMatrix = lcMatrix33(Focus->mModelWorld);
-		WorldToFocusMatrix = lcMatrix33AffineInverse(FocusToWorldMatrix);
+		lcObject* Focus = GetFocusObject();
 
-		RotationMatrix = lcMul(RotationMatrix, FocusToWorldMatrix);
+		if (Focus && Focus->IsPiece())
+		{
+			((lcPiece*)Focus)->RotatePivot(RotationMatrix);
+			Rotated = true;
+		}
 	}
 	else
-		WorldToFocusMatrix = lcMatrix33Identity();
-
-	bool Rotated = false;
-
-	for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
 	{
-		lcPiece* Piece = mPieces[PieceIdx];
+		float Bounds[6] = { FLT_MAX, FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX };
+		lcPiece* Focus = NULL;
+		lcPiece* Selected = NULL;
+		int NumSelected = 0;
 
-		if (!Piece->IsSelected())
-			continue;
+		for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
+		{
+			lcPiece* Piece = mPieces[PieceIdx];
 
-		lcVector3 Distance = Piece->mModelWorld.GetTranslation() - Center;
-		lcMatrix33 LocalToWorldMatrix = lcMatrix33(Piece->mModelWorld);
+			if (Piece->IsSelected())
+			{
+				if (Piece->IsFocused())
+					Focus = Piece;
 
-		lcMatrix33 LocalToFocusMatrix = lcMul(LocalToWorldMatrix, WorldToFocusMatrix);
-		lcMatrix33 NewLocalToWorldMatrix = lcMul(LocalToFocusMatrix, RotationMatrix);
+				Piece->CompareBoundingBox(Bounds);
 
-		lcMatrix33 WorldToLocalMatrix = lcMatrix33AffineInverse(LocalToWorldMatrix);
+				Selected = Piece;
+				NumSelected++;
+			}
+		}
 
-		Distance = lcMul(Distance, WorldToLocalMatrix);
-		Distance = lcMul(Distance, NewLocalToWorldMatrix);
+		lcVector3 Center;
 
-		NewLocalToWorldMatrix.Orthonormalize();
+		if (Focus)
+			Center = Focus->GetRotationCenter();
+		else if (NumSelected == 1)
+			Center = Selected->mModelWorld.GetTranslation();
+		else
+			Center = lcVector3((Bounds[0] + Bounds[3]) / 2.0f, (Bounds[1] + Bounds[4]) / 2.0f, (Bounds[2] + Bounds[5]) / 2.0f);
 
-		Piece->SetPosition(Center + Distance, mCurrentStep, gMainWindow->GetAddKeys());
-		Piece->SetRotation(NewLocalToWorldMatrix, mCurrentStep, gMainWindow->GetAddKeys());
-		Piece->UpdatePosition(mCurrentStep);
-		Rotated = true;
+		lcMatrix33 WorldToFocusMatrix;
+
+		if (!gMainWindow->GetRelativeTransform())
+			Focus = NULL;
+
+		if (Focus && Relative)
+		{
+			lcMatrix33 FocusToWorldMatrix = lcMatrix33(Focus->mModelWorld);
+			WorldToFocusMatrix = lcMatrix33AffineInverse(FocusToWorldMatrix);
+
+			RotationMatrix = lcMul(RotationMatrix, FocusToWorldMatrix);
+		}
+		else
+			WorldToFocusMatrix = lcMatrix33Identity();
+
+		for (int PieceIdx = 0; PieceIdx < mPieces.GetSize(); PieceIdx++)
+		{
+			lcPiece* Piece = mPieces[PieceIdx];
+
+			if (!Piece->IsSelected())
+				continue;
+
+			lcVector3 Distance = Piece->mModelWorld.GetTranslation() - Center;
+			lcMatrix33 LocalToWorldMatrix = lcMatrix33(Piece->mModelWorld);
+
+			lcMatrix33 LocalToFocusMatrix = lcMul(LocalToWorldMatrix, WorldToFocusMatrix);
+			lcMatrix33 NewLocalToWorldMatrix = lcMul(LocalToFocusMatrix, RotationMatrix);
+
+			lcMatrix33 WorldToLocalMatrix = lcMatrix33AffineInverse(LocalToWorldMatrix);
+
+			Distance = lcMul(Distance, WorldToLocalMatrix);
+			Distance = lcMul(Distance, NewLocalToWorldMatrix);
+
+			NewLocalToWorldMatrix.Orthonormalize();
+
+			Piece->SetPosition(Center + Distance, mCurrentStep, gMainWindow->GetAddKeys());
+			Piece->SetRotation(NewLocalToWorldMatrix, mCurrentStep, gMainWindow->GetAddKeys());
+			Piece->UpdatePosition(mCurrentStep);
+			Rotated = true;
+		}
 	}
 
 	if (Rotated && Update)
diff --git a/common/piece.cpp b/common/piece.cpp
index 9e32354a..5ed90302 100644
--- a/common/piece.cpp
+++ b/common/piece.cpp
@@ -16,7 +16,6 @@
 #include "lc_context.h"
 #include "lc_qutils.h"
 
-#define LC_PIECE_PIVOT_POINT_SIZE 10.0f
 #define LC_PIECE_CONTROL_POINT_SIZE 10.0f
 
 lcPiece::lcPiece(PieceInfo* Info)
@@ -497,32 +496,25 @@ void lcPiece::DrawInterface(lcContext* Context) const
 
 	if (IsPivotPointVisible())
 	{
-		float Verts[8 * 3];
-		float* CurVert = Verts;
-
-		lcVector3 Min = lcMul31(lcVector3(-LC_PIECE_PIVOT_POINT_SIZE, -LC_PIECE_PIVOT_POINT_SIZE, -LC_PIECE_PIVOT_POINT_SIZE), mPivotMatrix);
-		lcVector3 Max = lcMul31(lcVector3(LC_PIECE_PIVOT_POINT_SIZE, LC_PIECE_PIVOT_POINT_SIZE, LC_PIECE_PIVOT_POINT_SIZE), mPivotMatrix);
-
-		*CurVert++ = Min[0]; *CurVert++ = Min[1]; *CurVert++ = Min[2];
-		*CurVert++ = Min[0]; *CurVert++ = Max[1]; *CurVert++ = Min[2];
-		*CurVert++ = Max[0]; *CurVert++ = Max[1]; *CurVert++ = Min[2];
-		*CurVert++ = Max[0]; *CurVert++ = Min[1]; *CurVert++ = Min[2];
-		*CurVert++ = Min[0]; *CurVert++ = Min[1]; *CurVert++ = Max[2];
-		*CurVert++ = Min[0]; *CurVert++ = Max[1]; *CurVert++ = Max[2];
-		*CurVert++ = Max[0]; *CurVert++ = Max[1]; *CurVert++ = Max[2];
-		*CurVert++ = Max[0]; *CurVert++ = Min[1]; *CurVert++ = Max[2];
-
-		const GLushort Indices[36] =
+		const float Size = 5.0f;
+		const float Verts[8 * 3] =
 		{
-			0, 1, 2, 0, 2, 3, 7, 6, 5, 7, 5, 4, 0, 1, 5, 0, 5, 4,
-			2, 3, 7, 2, 7, 6, 0, 3, 7, 0, 7, 4, 1, 2, 6, 1, 6, 5
+			-Size, -Size, -Size, -Size,  Size, -Size, Size,  Size, -Size, Size, -Size, -Size,
+			-Size, -Size,  Size, -Size,  Size,  Size, Size,  Size,  Size, Size, -Size,  Size
 		};
 
+		const GLushort Indices[24] =
+		{
+			0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7
+		};
+
+		Context->SetWorldMatrix(lcMul(mPivotMatrix, mModelWorld));
+
 		Context->SetVertexBufferPointer(Verts);
 		Context->SetVertexFormat(0, 3, 0, 0);
 		Context->SetIndexBufferPointer(Indices);
 
-		Context->DrawIndexedPrimitives(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
+		Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, 0);
 	}
 
 	if (AreControlPointsVisible())
@@ -596,6 +588,15 @@ void lcPiece::Move(lcStep Step, bool AddKey, const lcVector3& Distance, bool Mov
 	}
 }
 
+void lcPiece::RotatePivot(const lcMatrix33& RotationMatrix)
+{
+	lcMatrix33 NewPivotRotationMatrix = lcMul(RotationMatrix, lcMatrix33(mPivotMatrix));
+	NewPivotRotationMatrix.Orthonormalize();
+
+	mPivotMatrix = lcMatrix44(NewPivotRotationMatrix, mPivotMatrix.GetTranslation());
+	mState |= LC_PIECE_PIVOT_POINT_VALID;
+}
+
 const char* lcPiece::GetName() const
 {
 	return mPieceInfo->m_strDescription;
diff --git a/common/piece.h b/common/piece.h
index 69939d12..668fdf40 100644
--- a/common/piece.h
+++ b/common/piece.h
@@ -270,7 +270,10 @@ public:
 		switch (Section)
 		{
 		case LC_PIECE_SECTION_POSITION:
-			return mModelWorld.GetTranslation();
+			if (mState & LC_PIECE_PIVOT_POINT_VALID)
+				return lcMul(mPivotMatrix, mModelWorld).GetTranslation();
+			else
+				return mModelWorld.GetTranslation();
 
 		case LC_PIECE_SECTION_CONTROL_POINT_1:
 			return lcMul31(mControlPoints[0].Position, mModelWorld);
@@ -342,6 +345,7 @@ public:
 
 	void UpdatePosition(lcStep Step);
 	void Move(lcStep Step, bool AddKey, const lcVector3& Distance, bool MovePivotPoint);
+	void RotatePivot(const lcMatrix33& RotationMatrix);
 
 	lcGroup* GetTopGroup();
 
@@ -401,13 +405,9 @@ public:
 	lcVector3 GetRotationCenter() const
 	{
 		if (mState & LC_PIECE_PIVOT_POINT_VALID)
-		{
 			return lcMul(mModelWorld, mPivotMatrix).GetTranslation();
-		}
 		else
-		{
 			return mModelWorld.GetTranslation();
-		}
 	}
 
 	lcMatrix44 GetRelativeRotation() const