mirror of
https://github.com/leozide/leocad
synced 2024-12-27 21:58:37 +01:00
1089 lines
38 KiB
C++
1089 lines
38 KiB
C++
#include "lc_global.h"
|
|
#include "lc_viewmanipulator.h"
|
|
#include "lc_view.h"
|
|
#include "lc_model.h"
|
|
#include "object.h"
|
|
#include "piece.h"
|
|
#include "camera.h"
|
|
#include "pieceinf.h"
|
|
#include "lc_synth.h"
|
|
#include "lc_traintrack.h"
|
|
#include "lc_mainwindow.h"
|
|
#include "texfont.h"
|
|
|
|
lcVertexBuffer lcViewManipulator::mRotateMoveVertexBuffer;
|
|
lcIndexBuffer lcViewManipulator::mRotateMoveIndexBuffer;
|
|
|
|
lcViewManipulator::lcViewManipulator(lcView* View)
|
|
: mView(View)
|
|
{
|
|
}
|
|
|
|
void lcViewManipulator::CreateResources(lcContext* Context)
|
|
{
|
|
float Verts[(51 + 138 + 10) * 3];
|
|
float* CurVert = Verts;
|
|
|
|
const float OverlayMovePlaneSize = 0.5f;
|
|
const float OverlayMoveArrowSize = 1.5f;
|
|
const float OverlayMoveArrowCapSize = 0.9f;
|
|
const float OverlayMoveArrowCapRadius = 0.1f;
|
|
const float OverlayMoveArrowBodySize = 1.2f;
|
|
const float OverlayMoveArrowBodyRadius = 0.05f;
|
|
const float OverlayRotateArrowStart = 1.0f;
|
|
const float OverlayRotateArrowEnd = 1.5f;
|
|
const float OverlayRotateArrowCenter = 1.2f;
|
|
|
|
*CurVert++ = OverlayMoveArrowSize; *CurVert++ = 0.0f; *CurVert++ = 0.0f;
|
|
|
|
for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++)
|
|
{
|
|
*CurVert++ = OverlayMoveArrowCapSize;
|
|
*CurVert++ = cosf(LC_2PI * EdgeIdx / 8) * OverlayMoveArrowCapRadius;
|
|
*CurVert++ = sinf(LC_2PI * EdgeIdx / 8) * OverlayMoveArrowCapRadius;
|
|
}
|
|
|
|
*CurVert++ = 0.0f; *CurVert++ = -OverlayMoveArrowBodyRadius; *CurVert++ = 0.0f;
|
|
*CurVert++ = 0.0f; *CurVert++ = OverlayMoveArrowBodyRadius; *CurVert++ = 0.0f;
|
|
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -OverlayMoveArrowBodyRadius;
|
|
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = OverlayMoveArrowBodyRadius;
|
|
*CurVert++ = OverlayMoveArrowBodySize; *CurVert++ = -OverlayMoveArrowBodyRadius; *CurVert++ = 0.0f;
|
|
*CurVert++ = OverlayMoveArrowBodySize; *CurVert++ = OverlayMoveArrowBodyRadius; *CurVert++ = 0.0f;
|
|
*CurVert++ = OverlayMoveArrowBodySize; *CurVert++ = 0.0f; *CurVert++ = -OverlayMoveArrowBodyRadius;
|
|
*CurVert++ = OverlayMoveArrowBodySize; *CurVert++ = 0.0f; *CurVert++ = OverlayMoveArrowBodyRadius;
|
|
|
|
for (int VertIdx = 0; VertIdx < 17; VertIdx++)
|
|
{
|
|
*CurVert = *(CurVert - 50); CurVert++;
|
|
*CurVert = *(CurVert - 52); CurVert++;
|
|
*CurVert = *(CurVert - 51); CurVert++;
|
|
}
|
|
|
|
for (int VertIdx = 0; VertIdx < 17; VertIdx++)
|
|
{
|
|
*CurVert = *(CurVert - 100); CurVert++;
|
|
*CurVert = *(CurVert - 102); CurVert++;
|
|
*CurVert = *(CurVert - 104); CurVert++;
|
|
}
|
|
|
|
*CurVert++ = 0.0f; *CurVert++ = OverlayRotateArrowEnd - OverlayMoveArrowCapRadius; *CurVert++ = OverlayRotateArrowStart;
|
|
|
|
for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++)
|
|
{
|
|
*CurVert++ = cosf(LC_2PI * EdgeIdx / 8) * OverlayMoveArrowCapRadius;
|
|
*CurVert++ = sinf(LC_2PI * EdgeIdx / 8) * OverlayMoveArrowCapRadius + OverlayRotateArrowEnd - OverlayMoveArrowCapRadius;
|
|
*CurVert++ = OverlayRotateArrowCenter;
|
|
}
|
|
|
|
*CurVert++ = 0.0f; *CurVert++ = OverlayRotateArrowStart; *CurVert++ = OverlayRotateArrowEnd - OverlayMoveArrowCapRadius;
|
|
|
|
for (int EdgeIdx = 0; EdgeIdx < 8; EdgeIdx++)
|
|
{
|
|
*CurVert++ = cosf(LC_2PI * EdgeIdx / 8) * OverlayMoveArrowCapRadius;
|
|
*CurVert++ = OverlayRotateArrowCenter;
|
|
*CurVert++ = sinf(LC_2PI * EdgeIdx / 8) * OverlayMoveArrowCapRadius + OverlayRotateArrowEnd - OverlayMoveArrowCapRadius;
|
|
}
|
|
|
|
for (int EdgeIdx = 0; EdgeIdx < 7; EdgeIdx++)
|
|
{
|
|
const float Radius1 = OverlayRotateArrowEnd - OverlayMoveArrowCapRadius - OverlayRotateArrowCenter - OverlayMoveArrowBodyRadius;
|
|
const float Radius2 = OverlayRotateArrowEnd - OverlayMoveArrowCapRadius - OverlayRotateArrowCenter + OverlayMoveArrowBodyRadius;
|
|
float x = cosf(LC_2PI / 4 * EdgeIdx / 6);
|
|
float y = sinf(LC_2PI / 4 * EdgeIdx / 6);
|
|
|
|
*CurVert++ = 0.0f;
|
|
*CurVert++ = OverlayRotateArrowCenter + x * Radius1;
|
|
*CurVert++ = OverlayRotateArrowCenter + y * Radius1;
|
|
*CurVert++ = 0.0f;
|
|
*CurVert++ = OverlayRotateArrowCenter + x * Radius2;
|
|
*CurVert++ = OverlayRotateArrowCenter + y * Radius2;
|
|
}
|
|
|
|
for (int EdgeIdx = 0; EdgeIdx < 7; EdgeIdx++)
|
|
{
|
|
const float Radius = OverlayRotateArrowEnd - OverlayMoveArrowCapRadius - OverlayRotateArrowCenter;
|
|
float x = cosf(LC_2PI / 4 * EdgeIdx / 6);
|
|
float y = sinf(LC_2PI / 4 * EdgeIdx / 6);
|
|
|
|
*CurVert++ = -OverlayMoveArrowBodyRadius;
|
|
*CurVert++ = OverlayRotateArrowCenter + x * Radius;
|
|
*CurVert++ = OverlayRotateArrowCenter + y * Radius;
|
|
*CurVert++ = OverlayMoveArrowBodyRadius;
|
|
*CurVert++ = OverlayRotateArrowCenter + x * Radius;
|
|
*CurVert++ = OverlayRotateArrowCenter + y * Radius;
|
|
}
|
|
|
|
for (int VertIdx = 0; VertIdx < 46; VertIdx++)
|
|
{
|
|
*CurVert = *(CurVert - 137); CurVert++;
|
|
*CurVert = *(CurVert - 139); CurVert++;
|
|
*CurVert = *(CurVert - 138); CurVert++;
|
|
}
|
|
|
|
for (int VertIdx = 0; VertIdx < 46; VertIdx++)
|
|
{
|
|
*CurVert = *(CurVert - 274); CurVert++;
|
|
*CurVert = *(CurVert - 276); CurVert++;
|
|
*CurVert = *(CurVert - 278); CurVert++;
|
|
}
|
|
|
|
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f;
|
|
*CurVert++ = 0.0f; *CurVert++ = OverlayMovePlaneSize; *CurVert++ = 0.0f;
|
|
*CurVert++ = 0.0f; *CurVert++ = OverlayMovePlaneSize; *CurVert++ = OverlayMovePlaneSize;
|
|
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = OverlayMovePlaneSize;
|
|
*CurVert++ = OverlayMovePlaneSize; *CurVert++ = 0.0f; *CurVert++ = 0.0f;
|
|
*CurVert++ = OverlayMovePlaneSize; *CurVert++ = 0.0f; *CurVert++ = OverlayMovePlaneSize;
|
|
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = OverlayMovePlaneSize;
|
|
*CurVert++ = 0.0f; *CurVert++ = OverlayMovePlaneSize; *CurVert++ = 0.0f;
|
|
*CurVert++ = OverlayMovePlaneSize; *CurVert++ = OverlayMovePlaneSize; *CurVert++ = 0.0f;
|
|
*CurVert++ = OverlayMovePlaneSize; *CurVert++ = 0.0f; *CurVert++ = 0.0f;
|
|
|
|
const GLushort Indices[108 + 360 + 12] =
|
|
{
|
|
0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 1,
|
|
9, 10, 14, 14, 13, 9, 11, 12, 15, 15, 16, 12,
|
|
17, 18, 19, 17, 19, 20, 17, 20, 21, 17, 21, 22, 17, 22, 23, 17, 23, 24, 17, 24, 25, 17, 25, 18,
|
|
26, 27, 31, 31, 30, 26, 28, 29, 32, 32, 33, 29,
|
|
34, 35, 36, 34, 36, 37, 34, 37, 38, 34, 38, 39, 34, 39, 40, 34, 40, 41, 34, 41, 42, 34, 42, 35,
|
|
43, 44, 48, 48, 47, 43, 45, 46, 49, 49, 50, 46,
|
|
51, 52, 53, 51, 53, 54, 51, 54, 55, 51, 55, 56, 51, 56, 57, 51, 57, 58, 51, 58, 59, 51, 59, 52,
|
|
60, 61, 62, 60, 62, 63, 60, 63, 64, 60, 64, 65, 60, 65, 66, 60, 66, 67, 60, 67, 68, 60, 68, 61,
|
|
69, 70, 71, 71, 72, 70, 71, 72, 73, 73, 74, 72, 73, 74, 75, 75, 76, 74, 75, 76, 77, 77, 78, 76, 77, 78, 79, 79, 80, 78, 79, 80, 81, 81, 82, 80,
|
|
83, 84, 85, 85, 86, 84, 85, 86, 87, 87, 88, 86, 87, 88, 89, 89, 90, 88, 89, 90, 91, 91, 92, 90, 91, 92, 93, 93, 94, 92, 93, 94, 95, 95, 96, 94,
|
|
97, 98, 99, 97, 99, 100, 97, 100, 101, 97, 101, 102, 97, 102, 103, 97, 103, 104, 97, 104, 105, 97, 105, 98,
|
|
106, 107, 108, 106, 108, 109, 106, 109, 110, 106, 110, 111, 106, 111, 112, 106, 112, 113, 106, 113, 114, 106, 114, 107,
|
|
115, 116, 117, 117, 118, 116, 117, 118, 119, 119, 120, 118, 119, 120, 121, 121, 122, 120, 121, 122, 123, 123, 124, 122, 123, 124, 125, 125, 126, 124, 125, 126, 127, 127, 128, 126,
|
|
129, 130, 131, 131, 132, 130, 131, 132, 133, 133, 134, 132, 133, 134, 135, 135, 136, 134, 135, 136, 137, 137, 138, 136, 137, 138, 139, 139, 140, 138, 139, 140, 141, 141, 142, 140,
|
|
143, 144, 145, 143, 145, 146, 143, 146, 147, 143, 147, 148, 143, 148, 149, 143, 149, 150, 143, 150, 151, 143, 151, 144,
|
|
152, 153, 154, 152, 154, 155, 152, 155, 156, 152, 156, 157, 152, 157, 158, 152, 158, 159, 152, 159, 160, 152, 160, 153,
|
|
161, 162, 163, 163, 164, 162, 163, 164, 165, 165, 166, 164, 165, 166, 167, 167, 168, 166, 167, 168, 169, 169, 170, 168, 169, 170, 171, 171, 172, 170, 171, 172, 173, 173, 174, 172,
|
|
175, 176, 177, 177, 178, 176, 177, 178, 179, 179, 180, 178, 179, 180, 181, 181, 182, 180, 181, 182, 183, 183, 184, 182, 183, 184, 185, 185, 186, 184, 185, 186, 187, 187, 188, 186,
|
|
189, 190, 191, 192, 189, 193, 194, 195, 189, 196, 197, 198
|
|
};
|
|
|
|
mRotateMoveVertexBuffer = Context->CreateVertexBuffer(sizeof(Verts), Verts);
|
|
mRotateMoveIndexBuffer = Context->CreateIndexBuffer(sizeof(Indices), Indices);
|
|
}
|
|
|
|
void lcViewManipulator::DestroyResources(lcContext* Context)
|
|
{
|
|
Context->DestroyVertexBuffer(mRotateMoveVertexBuffer);
|
|
Context->DestroyIndexBuffer(mRotateMoveIndexBuffer);
|
|
}
|
|
|
|
void lcViewManipulator::DrawSelectMove(lcTrackButton TrackButton, lcTrackTool TrackTool)
|
|
{
|
|
const lcCamera* Camera = mView->GetCamera();
|
|
lcContext* Context = mView->mContext;
|
|
|
|
Context->SetMaterial(lcMaterialType::UnlitColor);
|
|
Context->SetViewMatrix(Camera->mWorldView);
|
|
Context->SetProjectionMatrix(mView->GetProjectionMatrix());
|
|
|
|
Context->EnableDepthTest(false);
|
|
|
|
lcVector3 OverlayCenter;
|
|
lcMatrix33 RelativeRotation;
|
|
lcModel* ActiveModel = mView->GetActiveModel();
|
|
ActiveModel->GetMoveRotateTransform(OverlayCenter, RelativeRotation);
|
|
bool AnyPiecesSelected = ActiveModel->AnyPiecesSelected();
|
|
|
|
lcMatrix44 WorldMatrix = lcMatrix44(RelativeRotation, OverlayCenter);
|
|
|
|
if (ActiveModel != mView->GetModel())
|
|
WorldMatrix = lcMul(WorldMatrix, mView->GetActiveSubmodelTransform());
|
|
|
|
const float OverlayScale = mView->GetOverlayScale();
|
|
WorldMatrix = lcMul(lcMatrix44Scale(lcVector3(OverlayScale, OverlayScale, OverlayScale)), WorldMatrix);
|
|
|
|
Context->SetWorldMatrix(WorldMatrix);
|
|
Context->SetLineWidth(1.0f);
|
|
|
|
Context->SetIndexBuffer(mRotateMoveIndexBuffer);
|
|
Context->SetVertexBuffer(mRotateMoveVertexBuffer);
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
lcObject* Focus = ActiveModel->GetFocusObject();
|
|
quint32 AllowedTransforms = Focus ? Focus->GetAllowedTransforms() : LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z | LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z;
|
|
|
|
if (TrackButton == lcTrackButton::None || (TrackTool >= lcTrackTool::MoveX && TrackTool <= lcTrackTool::MoveXYZ))
|
|
{
|
|
if (AllowedTransforms & LC_OBJECT_TRANSFORM_MOVE_X)
|
|
{
|
|
if ((TrackTool == lcTrackTool::MoveX) || (TrackTool == lcTrackTool::MoveXY) || (TrackTool == lcTrackTool::MoveXZ))
|
|
{
|
|
Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
|
|
}
|
|
else if (TrackButton == lcTrackButton::None)
|
|
{
|
|
Context->SetColor(0.8f, 0.0f, 0.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
|
|
}
|
|
}
|
|
|
|
if (AllowedTransforms & LC_OBJECT_TRANSFORM_MOVE_Y)
|
|
{
|
|
if (((TrackTool == lcTrackTool::MoveY) || (TrackTool == lcTrackTool::MoveXY) || (TrackTool == lcTrackTool::MoveYZ)) && (AllowedTransforms & LC_OBJECT_TRANSFORM_MOVE_Y))
|
|
{
|
|
Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 36 * 2);
|
|
}
|
|
else if (TrackButton == lcTrackButton::None)
|
|
{
|
|
Context->SetColor(0.0f, 0.8f, 0.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 36 * 2);
|
|
}
|
|
}
|
|
|
|
if (AllowedTransforms & LC_OBJECT_TRANSFORM_MOVE_Z)
|
|
{
|
|
if (((TrackTool == lcTrackTool::MoveZ) || (TrackTool == lcTrackTool::MoveXZ) || (TrackTool == lcTrackTool::MoveYZ)) && (AllowedTransforms & LC_OBJECT_TRANSFORM_MOVE_Z))
|
|
{
|
|
Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 72 * 2);
|
|
}
|
|
else if (TrackButton == lcTrackButton::None)
|
|
{
|
|
Context->SetColor(0.0f, 0.0f, 0.8f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 72 * 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gMainWindow->GetTool() == lcTool::Select && TrackButton == lcTrackButton::None && AnyPiecesSelected)
|
|
{
|
|
if (AllowedTransforms & LC_OBJECT_TRANSFORM_ROTATE_X)
|
|
{
|
|
if (TrackTool == lcTrackTool::RotateX)
|
|
Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f);
|
|
else
|
|
Context->SetColor(0.8f, 0.0f, 0.0f, 1.0f);
|
|
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 120, GL_UNSIGNED_SHORT, 108 * 2);
|
|
}
|
|
|
|
if (AllowedTransforms & LC_OBJECT_TRANSFORM_ROTATE_Y)
|
|
{
|
|
if (TrackTool == lcTrackTool::RotateY)
|
|
Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f);
|
|
else
|
|
Context->SetColor(0.0f, 0.8f, 0.0f, 1.0f);
|
|
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 120, GL_UNSIGNED_SHORT, (108 + 120) * 2);
|
|
}
|
|
|
|
if (AllowedTransforms & LC_OBJECT_TRANSFORM_ROTATE_Z)
|
|
{
|
|
if (TrackTool == lcTrackTool::RotateZ)
|
|
Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f);
|
|
else
|
|
Context->SetColor(0.0f, 0.0f, 0.8f, 1.0f);
|
|
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 120, GL_UNSIGNED_SHORT, (108 + 240) * 2);
|
|
}
|
|
}
|
|
|
|
if ((TrackTool == lcTrackTool::MoveXY) || (TrackTool == lcTrackTool::MoveXZ) || (TrackTool == lcTrackTool::MoveYZ))
|
|
{
|
|
Context->EnableColorBlend(true);
|
|
|
|
Context->SetColor(0.8f, 0.8f, 0.0f, 0.3f);
|
|
|
|
if (TrackTool == lcTrackTool::MoveXY)
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, (108 + 360 + 8) * 2);
|
|
else if (TrackTool == lcTrackTool::MoveXZ)
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, (108 + 360 + 4) * 2);
|
|
else if (TrackTool == lcTrackTool::MoveYZ)
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, (108 + 360) * 2);
|
|
|
|
Context->EnableColorBlend(false);
|
|
}
|
|
|
|
if (Focus && Focus->IsPiece())
|
|
{
|
|
lcPiece* Piece = (lcPiece*)Focus;
|
|
quint32 Section = Piece->GetFocusSection();
|
|
|
|
if (Section >= LC_PIECE_SECTION_CONTROL_POINT_FIRST && Section <= LC_PIECE_SECTION_CONTROL_POINT_LAST && Piece->mPieceInfo->GetSynthInfo() && Piece->mPieceInfo->GetSynthInfo()->IsCurve())
|
|
{
|
|
int ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_FIRST;
|
|
float Strength = Piece->GetControlPoints()[ControlPointIndex].Scale;
|
|
const float ScaleStart = 2.0f;
|
|
float Length = ScaleStart + Strength / OverlayScale;
|
|
const float OverlayScaleInnerRadius = 0.075f;
|
|
const float OverlayScaleRadius = 0.125f;
|
|
|
|
lcVector3 Verts[38];
|
|
int NumVerts = 0;
|
|
|
|
Verts[NumVerts++] = lcVector3(Length - OverlayScaleRadius, 0.0f, 0.0f);
|
|
Verts[NumVerts++] = lcVector3(OverlayScaleRadius - Length, 0.0f, 0.0f);
|
|
|
|
float SinTable[9], CosTable[9];
|
|
|
|
for (int Step = 0; Step <= 8; Step++)
|
|
{
|
|
SinTable[Step] = sinf((float)Step / 8.0f * LC_2PI);
|
|
CosTable[Step] = cosf((float)Step / 8.0f * LC_2PI);
|
|
}
|
|
|
|
for (int Step = 0; Step <= 8; Step++)
|
|
{
|
|
float x = CosTable[Step];
|
|
float y = SinTable[Step];
|
|
|
|
Verts[NumVerts++] = lcVector3(Length + x * OverlayScaleInnerRadius, 0.0f, y * OverlayScaleInnerRadius);
|
|
Verts[NumVerts++] = lcVector3(Length + x * OverlayScaleRadius, 0.0f, y * OverlayScaleRadius);
|
|
}
|
|
|
|
for (int Step = 0; Step <= 8; Step++)
|
|
{
|
|
float x = CosTable[Step];
|
|
float y = SinTable[Step];
|
|
|
|
Verts[NumVerts++] = lcVector3(-Length + x * OverlayScaleInnerRadius, 0.0f, y * OverlayScaleInnerRadius);
|
|
Verts[NumVerts++] = lcVector3(-Length + x * OverlayScaleRadius, 0.0f, y * OverlayScaleRadius);
|
|
}
|
|
|
|
if (TrackTool == lcTrackTool::ScalePlus || TrackTool == lcTrackTool::ScaleMinus)
|
|
Context->SetColor(0.8f, 0.8f, 0.0f, 0.3f);
|
|
else
|
|
Context->SetColor(0.0f, 0.0f, 0.8f, 1.0f);
|
|
|
|
Context->SetVertexBufferPointer(Verts);
|
|
Context->ClearIndexBuffer();
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
Context->DrawPrimitives(GL_LINES, 0, 2);
|
|
Context->DrawPrimitives(GL_TRIANGLE_STRIP, 2, 18);
|
|
Context->DrawPrimitives(GL_TRIANGLE_STRIP, 20, 18);
|
|
}
|
|
else if (Piece->mPieceInfo->GetTrainTrackInfo())
|
|
{
|
|
DrawTrainTrack(Piece, Context, OverlayScale);
|
|
}
|
|
}
|
|
|
|
Context->EnableDepthTest(true);
|
|
}
|
|
|
|
void lcViewManipulator::DrawTrainTrack(lcPiece* Piece, lcContext* Context, float OverlayScale)
|
|
{
|
|
const lcTrainTrackInfo* TrainTrackInfo = Piece->mPieceInfo->GetTrainTrackInfo();
|
|
const std::vector<lcTrainTrackConnection>& Connections = TrainTrackInfo->GetConnections();
|
|
|
|
for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++)
|
|
{
|
|
if (Piece->IsTrainTrackConnected(ConnectionIndex))
|
|
continue;
|
|
|
|
const lcMatrix44& Transform = Connections[ConnectionIndex].Transform;
|
|
|
|
lcVector3 Verts[static_cast<int>(lcTrainTrackType::Count) * 2];
|
|
int NumVerts = 0;
|
|
|
|
Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale;
|
|
Verts[NumVerts++] = (Transform.GetTranslation() + lcVector3(Transform[0]) * 100) / OverlayScale;
|
|
|
|
Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale;
|
|
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 60)) * 100) / OverlayScale;
|
|
|
|
Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale;
|
|
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -60)) * 100) / OverlayScale;
|
|
|
|
Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale;
|
|
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 30)) * 100) / OverlayScale;
|
|
|
|
Verts[NumVerts++] = Transform.GetTranslation() / OverlayScale;
|
|
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -30)) * 100) / OverlayScale;
|
|
|
|
Context->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
Context->SetVertexBufferPointer(Verts);
|
|
Context->ClearIndexBuffer();
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
Context->DrawPrimitives(GL_LINES, 0, NumVerts);
|
|
}
|
|
}
|
|
|
|
void lcViewManipulator::DrawRotate(lcTrackButton TrackButton, lcTrackTool TrackTool)
|
|
{
|
|
const lcCamera* Camera = mView->GetCamera();
|
|
lcContext* Context = mView->mContext;
|
|
|
|
const float OverlayScale = mView->GetOverlayScale();
|
|
const float OverlayRotateRadius = 2.0f;
|
|
|
|
Context->SetMaterial(lcMaterialType::UnlitColor);
|
|
Context->SetViewMatrix(Camera->mWorldView);
|
|
Context->SetProjectionMatrix(mView->GetProjectionMatrix());
|
|
Context->SetLineWidth(1.0f);
|
|
|
|
Context->EnableDepthTest(false);
|
|
|
|
int j;
|
|
|
|
lcVector3 OverlayCenter;
|
|
lcMatrix33 RelativeRotation;
|
|
lcModel* ActiveModel = mView->GetActiveModel();
|
|
ActiveModel->GetMoveRotateTransform(OverlayCenter, RelativeRotation);
|
|
lcVector3 MouseToolDistance = ActiveModel->SnapRotation(ActiveModel->GetMouseToolDistance());
|
|
bool HasAngle = false;
|
|
|
|
lcMatrix44 WorldMatrix = lcMatrix44(RelativeRotation, OverlayCenter);
|
|
|
|
if (ActiveModel != mView->GetModel())
|
|
WorldMatrix = lcMul(WorldMatrix, mView->GetActiveSubmodelTransform());
|
|
|
|
// Draw a disc showing the rotation amount.
|
|
if (MouseToolDistance.LengthSquared() != 0.0f && (TrackButton != lcTrackButton::None))
|
|
{
|
|
lcVector4 Rotation;
|
|
float Angle, Step;
|
|
|
|
HasAngle = true;
|
|
|
|
switch (TrackTool)
|
|
{
|
|
case lcTrackTool::RotateX:
|
|
Context->SetColor(0.8f, 0.0f, 0.0f, 0.3f);
|
|
Angle = MouseToolDistance[0];
|
|
Rotation = lcVector4(0.0f, 0.0f, 0.0f, 1.0f);
|
|
break;
|
|
case lcTrackTool::RotateY:
|
|
Context->SetColor(0.0f, 0.8f, 0.0f, 0.3f);
|
|
Angle = MouseToolDistance[1];
|
|
Rotation = lcVector4(90.0f, 0.0f, 0.0f, 1.0f);
|
|
break;
|
|
case lcTrackTool::RotateZ:
|
|
Context->SetColor(0.0f, 0.0f, 0.8f, 0.3f);
|
|
Angle = MouseToolDistance[2];
|
|
Rotation = lcVector4(90.0f, 0.0f, -1.0f, 0.0f);
|
|
break;
|
|
default:
|
|
Rotation = lcVector4(0.0f, 0.0f, 0.0f, 1.0f);
|
|
Angle = 0.0f;
|
|
break;
|
|
};
|
|
|
|
if (Angle > 0.0f)
|
|
{
|
|
Step = 360.0f / 32;
|
|
}
|
|
else
|
|
{
|
|
Angle = -Angle;
|
|
Step = -360.0f / 32;
|
|
}
|
|
|
|
if (fabsf(Angle) >= fabsf(Step))
|
|
{
|
|
lcMatrix44 RotatedWorldMatrix = lcMul(lcMatrix44FromAxisAngle(lcVector3(Rotation[1], Rotation[2], Rotation[3]), Rotation[0] * LC_DTOR), WorldMatrix);
|
|
|
|
Context->SetWorldMatrix(RotatedWorldMatrix);
|
|
|
|
Context->EnableColorBlend(true);
|
|
|
|
lcVector3 Verts[33];
|
|
Verts[0] = lcVector3(0.0f, 0.0f, 0.0f);
|
|
int NumVerts = 1;
|
|
|
|
Context->SetVertexBufferPointer(Verts);
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
float StartAngle;
|
|
int i = 0;
|
|
|
|
if (Step < 0)
|
|
StartAngle = -Angle;
|
|
else
|
|
StartAngle = Angle;
|
|
|
|
do
|
|
{
|
|
float x = cosf((Step * i - StartAngle) * LC_DTOR) * OverlayRotateRadius * OverlayScale;
|
|
float y = sinf((Step * i - StartAngle) * LC_DTOR) * OverlayRotateRadius * OverlayScale;
|
|
|
|
Verts[NumVerts++] = lcVector3(0.0f, x, y);
|
|
|
|
if (NumVerts == 33)
|
|
{
|
|
Context->DrawPrimitives(GL_TRIANGLE_FAN, 0, NumVerts);
|
|
Verts[1] = Verts[32];
|
|
NumVerts = 2;
|
|
}
|
|
|
|
i++;
|
|
if (Step > 0)
|
|
Angle -= Step;
|
|
else
|
|
Angle += Step;
|
|
|
|
} while (Angle >= 0.0f);
|
|
|
|
if (NumVerts > 2)
|
|
Context->DrawPrimitives(GL_TRIANGLE_FAN, 0, NumVerts);
|
|
|
|
Context->EnableColorBlend(false);
|
|
}
|
|
}
|
|
|
|
// Draw the circles.
|
|
if (gMainWindow->GetTool() == lcTool::Rotate && !HasAngle && TrackButton == lcTrackButton::None)
|
|
{
|
|
lcMatrix44 Mat = lcMatrix44AffineInverse(Camera->mWorldView);
|
|
Mat.SetTranslation(WorldMatrix.GetTranslation());
|
|
|
|
lcVector3 Verts[32];
|
|
|
|
for (j = 0; j < 32; j++)
|
|
{
|
|
lcVector3 Pt;
|
|
|
|
Pt[0] = cosf(LC_2PI * j / 32) * OverlayRotateRadius * OverlayScale;
|
|
Pt[1] = sinf(LC_2PI * j / 32) * OverlayRotateRadius * OverlayScale;
|
|
Pt[2] = 0.0f;
|
|
|
|
Verts[j] = lcMul31(Pt, Mat);
|
|
}
|
|
|
|
Context->SetColor(0.1f, 0.1f, 0.1f, 1.0f);
|
|
Context->SetWorldMatrix(lcMatrix44Identity());
|
|
|
|
Context->SetVertexBufferPointer(Verts);
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
Context->DrawPrimitives(GL_LINE_LOOP, 0, 32);
|
|
}
|
|
|
|
lcVector3 ViewDir = Camera->mTargetPosition - Camera->mPosition;
|
|
ViewDir.Normalize();
|
|
|
|
// Transform ViewDir to local space.
|
|
ViewDir = lcMul(ViewDir, lcMatrix33AffineInverse(lcMatrix33(WorldMatrix)));
|
|
|
|
Context->SetWorldMatrix(WorldMatrix);
|
|
|
|
// Draw each axis circle.
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
if (static_cast<int>(TrackTool) == static_cast<int>(lcTrackTool::RotateX) + i)
|
|
{
|
|
Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
if (gMainWindow->GetTool() != lcTool::Rotate || HasAngle || TrackButton != lcTrackButton::None)
|
|
continue;
|
|
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
Context->SetColor(0.8f, 0.0f, 0.0f, 1.0f);
|
|
break;
|
|
case 1:
|
|
Context->SetColor(0.0f, 0.8f, 0.0f, 1.0f);
|
|
break;
|
|
case 2:
|
|
Context->SetColor(0.0f, 0.0f, 0.8f, 1.0f);
|
|
break;
|
|
}
|
|
}
|
|
|
|
lcVector3 Verts[64];
|
|
int NumVerts = 0;
|
|
|
|
for (j = 0; j < 32; j++)
|
|
{
|
|
lcVector3 v1, v2;
|
|
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
v1 = lcVector3(0.0f, cosf(LC_2PI * j / 32), sinf(LC_2PI * j / 32));
|
|
v2 = lcVector3(0.0f, cosf(LC_2PI * (j + 1) / 32), sinf(LC_2PI * (j + 1) / 32));
|
|
break;
|
|
|
|
case 1:
|
|
v1 = lcVector3(cosf(LC_2PI * j / 32), 0.0f, sinf(LC_2PI * j / 32));
|
|
v2 = lcVector3(cosf(LC_2PI * (j + 1) / 32), 0.0f, sinf(LC_2PI * (j + 1) / 32));
|
|
break;
|
|
|
|
case 2:
|
|
v1 = lcVector3(cosf(LC_2PI * j / 32), sinf(LC_2PI * j / 32), 0.0f);
|
|
v2 = lcVector3(cosf(LC_2PI * (j + 1) / 32), sinf(LC_2PI * (j + 1) / 32), 0.0f);
|
|
break;
|
|
}
|
|
|
|
if (gMainWindow->GetTool() != lcTool::Rotate || HasAngle || TrackButton != lcTrackButton::None || lcDot(ViewDir, v1 + v2) <= 0.0f)
|
|
{
|
|
Verts[NumVerts++] = v1 * (OverlayRotateRadius * OverlayScale);
|
|
Verts[NumVerts++] = v2 * (OverlayRotateRadius * OverlayScale);
|
|
}
|
|
}
|
|
|
|
Context->SetVertexBufferPointer(Verts);
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
Context->DrawPrimitives(GL_LINES, 0, NumVerts);
|
|
}
|
|
|
|
// Draw tangent vector.
|
|
if (TrackButton != lcTrackButton::None && ((TrackTool == lcTrackTool::RotateX) || (TrackTool == lcTrackTool::RotateY) || (TrackTool == lcTrackTool::RotateZ)))
|
|
{
|
|
const float OverlayRotateArrowSize = 1.5f;
|
|
const float OverlayRotateArrowCapSize = 0.25f;
|
|
|
|
lcVector4 Rotation;
|
|
float Angle;
|
|
|
|
switch (TrackTool)
|
|
{
|
|
case lcTrackTool::RotateX:
|
|
Angle = MouseToolDistance[0];
|
|
Rotation = lcVector4(0.0f, 0.0f, 0.0f, 1.0f);
|
|
break;
|
|
case lcTrackTool::RotateY:
|
|
Angle = MouseToolDistance[1];
|
|
Rotation = lcVector4(90.0f, 0.0f, 0.0f, 1.0f);
|
|
break;
|
|
case lcTrackTool::RotateZ:
|
|
Angle = MouseToolDistance[2];
|
|
Rotation = lcVector4(90.0f, 0.0f, -1.0f, 0.0f);
|
|
break;
|
|
default:
|
|
Angle = 0.0f;
|
|
Rotation = lcVector4(0.0f, 0.0f, 1.0f, 0.0f);
|
|
break;
|
|
};
|
|
|
|
lcMatrix44 RotatedWorldMatrix = lcMul(lcMatrix44FromAxisAngle(lcVector3(Rotation[1], Rotation[2], Rotation[3]), Rotation[0] * LC_DTOR), WorldMatrix);
|
|
Context->SetWorldMatrix(RotatedWorldMatrix);
|
|
|
|
Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f);
|
|
|
|
if (HasAngle)
|
|
{
|
|
float StartY = OverlayScale * OverlayRotateRadius;
|
|
float EndZ = (Angle > 0.0f) ? OverlayScale * OverlayRotateArrowSize : -OverlayScale * OverlayRotateArrowSize;
|
|
float TipZ = (Angle > 0.0f) ? -OverlayScale * OverlayRotateArrowCapSize : OverlayScale * OverlayRotateArrowCapSize;
|
|
|
|
lcVector3 Verts[6];
|
|
|
|
Verts[0] = lcVector3(0.0f, StartY, 0.0f);
|
|
Verts[1] = lcVector3(0.0f, StartY, EndZ);
|
|
|
|
Verts[2] = lcVector3(0.0f, StartY, EndZ);
|
|
Verts[3] = lcVector3(0.0f, StartY + OverlayScale * OverlayRotateArrowCapSize, EndZ + TipZ);
|
|
|
|
Verts[4] = lcVector3(0.0f, StartY, EndZ);
|
|
Verts[5] = lcVector3(0.0f, StartY - OverlayScale * OverlayRotateArrowCapSize, EndZ + TipZ);
|
|
|
|
Context->SetVertexBufferPointer(Verts);
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
Context->DrawPrimitives(GL_LINES, 0, 6);
|
|
}
|
|
|
|
// Draw text.
|
|
lcVector3 ScreenPos = mView->ProjectPoint(WorldMatrix.GetTranslation());
|
|
|
|
Context->SetMaterial(lcMaterialType::UnlitTextureModulate);
|
|
Context->SetWorldMatrix(lcMatrix44Identity());
|
|
Context->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
|
|
Context->SetProjectionMatrix(lcMatrix44Ortho(0.0f, mView->GetWidth(), 0.0f, mView->GetHeight(), -1.0f, 1.0f));
|
|
Context->BindTexture2D(gTexFont.GetTexture());
|
|
Context->EnableColorBlend(true);
|
|
|
|
char buf[32];
|
|
sprintf(buf, "[%.2f]", fabsf(Angle));
|
|
|
|
int cx, cy;
|
|
gTexFont.GetStringDimensions(&cx, &cy, buf);
|
|
|
|
Context->SetColor(0.8f, 0.8f, 0.0f, 1.0f);
|
|
gTexFont.PrintText(Context, ScreenPos[0] - (cx / 2), ScreenPos[1] + (cy / 2), 0.0f, buf);
|
|
|
|
Context->EnableColorBlend(false);
|
|
}
|
|
|
|
Context->EnableDepthTest(true);
|
|
}
|
|
|
|
bool lcViewManipulator::IsTrackToolAllowed(lcTrackTool TrackTool, quint32 AllowedTransforms)
|
|
{
|
|
switch (TrackTool)
|
|
{
|
|
case lcTrackTool::None:
|
|
case lcTrackTool::Insert:
|
|
case lcTrackTool::PointLight:
|
|
case lcTrackTool::SpotLight:
|
|
case lcTrackTool::DirectionalLight:
|
|
case lcTrackTool::AreaLight:
|
|
case lcTrackTool::Camera:
|
|
case lcTrackTool::Select:
|
|
return true;
|
|
|
|
case lcTrackTool::MoveX:
|
|
return AllowedTransforms & LC_OBJECT_TRANSFORM_MOVE_X;
|
|
|
|
case lcTrackTool::MoveY:
|
|
return AllowedTransforms & LC_OBJECT_TRANSFORM_MOVE_Y;
|
|
|
|
case lcTrackTool::MoveZ:
|
|
return AllowedTransforms & LC_OBJECT_TRANSFORM_MOVE_Z;
|
|
|
|
case lcTrackTool::MoveXY:
|
|
return (AllowedTransforms & (LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y)) == (LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y);
|
|
|
|
case lcTrackTool::MoveXZ:
|
|
return (AllowedTransforms & (LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Z)) == (LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Z);
|
|
|
|
case lcTrackTool::MoveYZ:
|
|
return (AllowedTransforms & (LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z)) == (LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z);
|
|
|
|
case lcTrackTool::MoveXYZ:
|
|
return (AllowedTransforms & (LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z)) == (LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z);
|
|
|
|
case lcTrackTool::RotateX:
|
|
return AllowedTransforms & LC_OBJECT_TRANSFORM_ROTATE_X;
|
|
|
|
case lcTrackTool::RotateY:
|
|
return AllowedTransforms & LC_OBJECT_TRANSFORM_ROTATE_Y;
|
|
|
|
case lcTrackTool::RotateZ:
|
|
return AllowedTransforms & LC_OBJECT_TRANSFORM_ROTATE_Z;
|
|
|
|
case lcTrackTool::RotateXY:
|
|
return (AllowedTransforms & (LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y)) == (LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y);
|
|
|
|
case lcTrackTool::RotateXYZ:
|
|
return (AllowedTransforms & (LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z)) == (LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z);
|
|
|
|
case lcTrackTool::RotateTrainTrack:
|
|
return true;
|
|
|
|
case lcTrackTool::ScalePlus:
|
|
case lcTrackTool::ScaleMinus:
|
|
return AllowedTransforms & (LC_OBJECT_TRANSFORM_SCALE_X | LC_OBJECT_TRANSFORM_SCALE_Y | LC_OBJECT_TRANSFORM_SCALE_Z);
|
|
|
|
case lcTrackTool::Eraser:
|
|
case lcTrackTool::Paint:
|
|
case lcTrackTool::ColorPicker:
|
|
case lcTrackTool::Zoom:
|
|
case lcTrackTool::Pan:
|
|
case lcTrackTool::OrbitX:
|
|
case lcTrackTool::OrbitY:
|
|
case lcTrackTool::OrbitXY:
|
|
case lcTrackTool::Roll:
|
|
case lcTrackTool::ZoomRegion:
|
|
return true;
|
|
|
|
case lcTrackTool::Count:
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
std::pair<lcTrackTool, quint32> lcViewManipulator::UpdateSelectMove()
|
|
{
|
|
lcModel* ActiveModel = mView->GetActiveModel();
|
|
const float OverlayScale = mView->GetOverlayScale();
|
|
const float OverlayMovePlaneSize = 0.5f * OverlayScale;
|
|
const float OverlayMoveArrowSize = 1.5f * OverlayScale;
|
|
const float OverlayMoveArrowCapRadius = 0.1f * OverlayScale;
|
|
const float OverlayRotateArrowStart = 1.0f * OverlayScale;
|
|
const float OverlayRotateArrowEnd = 1.5f * OverlayScale;
|
|
const float OverlayScaleRadius = 0.125f;
|
|
|
|
lcTool CurrentTool = gMainWindow->GetTool();
|
|
lcTrackTool NewTrackTool = (CurrentTool == lcTool::Move) ? lcTrackTool::MoveXYZ : lcTrackTool::Select;
|
|
quint32 NewTrackSection = ~0U;
|
|
|
|
lcVector3 OverlayCenter;
|
|
lcMatrix33 RelativeRotation;
|
|
|
|
if (!ActiveModel->GetMoveRotateTransform(OverlayCenter, RelativeRotation))
|
|
return { NewTrackTool, NewTrackSection };
|
|
|
|
lcMatrix44 WorldMatrix = lcMatrix44(RelativeRotation, OverlayCenter);
|
|
|
|
if (ActiveModel != mView->GetModel())
|
|
WorldMatrix = lcMul(WorldMatrix, mView->GetActiveSubmodelTransform());
|
|
OverlayCenter = WorldMatrix.GetTranslation();
|
|
|
|
lcVector3 PlaneNormals[3] =
|
|
{
|
|
lcVector3(1.0f, 0.0f, 0.0f),
|
|
lcVector3(0.0f, 1.0f, 0.0f),
|
|
lcVector3(0.0f, 0.0f, 1.0f),
|
|
};
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
PlaneNormals[i] = lcMul30(PlaneNormals[i], WorldMatrix);
|
|
|
|
const int x = mView->GetMouseX();
|
|
const int y = mView->GetMouseY();
|
|
lcVector3 StartEnd[2] = { lcVector3((float)x, (float)y, 0.0f), lcVector3((float)x, (float)y, 1.0f) };
|
|
mView->UnprojectPoints(StartEnd, 2);
|
|
const lcVector3& Start = StartEnd[0];
|
|
const lcVector3& End = StartEnd[1];
|
|
float ClosestIntersectionDistance = FLT_MAX;
|
|
|
|
lcObject* Focus = ActiveModel->GetFocusObject();
|
|
int ControlPointIndex = -1;
|
|
|
|
if (Focus && Focus->IsPiece())
|
|
{
|
|
lcPiece* Piece = (lcPiece*)Focus;
|
|
quint32 Section = Piece->GetFocusSection();
|
|
|
|
if (Section >= LC_PIECE_SECTION_CONTROL_POINT_FIRST && Section <= LC_PIECE_SECTION_CONTROL_POINT_LAST)
|
|
ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_FIRST;
|
|
}
|
|
|
|
quint32 AllowedTransforms = Focus ? Focus->GetAllowedTransforms() : LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ;
|
|
|
|
for (int AxisIndex = 0; AxisIndex < 3; AxisIndex++)
|
|
{
|
|
lcVector4 Plane(PlaneNormals[AxisIndex], -lcDot(PlaneNormals[AxisIndex], OverlayCenter));
|
|
lcVector3 Intersection;
|
|
|
|
if (!lcLineSegmentPlaneIntersection(&Intersection, Start, End, Plane))
|
|
continue;
|
|
|
|
float IntersectionDistance = lcLengthSquared(Intersection - Start);
|
|
|
|
if (IntersectionDistance > ClosestIntersectionDistance)
|
|
continue;
|
|
|
|
lcVector3 Dir(Intersection - OverlayCenter);
|
|
|
|
float Proj1 = lcDot(Dir, PlaneNormals[(AxisIndex + 1) % 3]);
|
|
float Proj2 = lcDot(Dir, PlaneNormals[(AxisIndex + 2) % 3]);
|
|
|
|
if (Proj1 > 0.0f && Proj1 < OverlayMovePlaneSize && Proj2 > 0.0f && Proj2 < OverlayMovePlaneSize)
|
|
{
|
|
lcTrackTool PlaneModes[] = { lcTrackTool::MoveYZ, lcTrackTool::MoveXZ, lcTrackTool::MoveXY };
|
|
|
|
if (IsTrackToolAllowed(PlaneModes[AxisIndex], AllowedTransforms))
|
|
{
|
|
NewTrackTool = PlaneModes[AxisIndex];
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
}
|
|
}
|
|
|
|
if (CurrentTool == lcTool::Select && Proj1 > OverlayRotateArrowStart && Proj1 < OverlayRotateArrowEnd && Proj2 > OverlayRotateArrowStart && Proj2 < OverlayRotateArrowEnd && ActiveModel->AnyPiecesSelected())
|
|
{
|
|
lcTrackTool PlaneModes[] = { lcTrackTool::RotateX, lcTrackTool::RotateY, lcTrackTool::RotateZ };
|
|
|
|
if (IsTrackToolAllowed(PlaneModes[AxisIndex], AllowedTransforms))
|
|
{
|
|
NewTrackTool = PlaneModes[AxisIndex];
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
}
|
|
}
|
|
|
|
if (fabs(Proj1) < OverlayMoveArrowCapRadius && Proj2 > 0.0f && Proj2 < OverlayMoveArrowSize)
|
|
{
|
|
lcTrackTool DirModes[] = { lcTrackTool::MoveZ, lcTrackTool::MoveX, lcTrackTool::MoveY };
|
|
|
|
if (IsTrackToolAllowed(DirModes[AxisIndex], AllowedTransforms))
|
|
{
|
|
NewTrackTool = DirModes[AxisIndex];
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
}
|
|
}
|
|
|
|
if (fabs(Proj2) < OverlayMoveArrowCapRadius && Proj1 > 0.0f && Proj1 < OverlayMoveArrowSize)
|
|
{
|
|
lcTrackTool DirModes[] = { lcTrackTool::MoveY, lcTrackTool::MoveZ, lcTrackTool::MoveX };
|
|
|
|
if (IsTrackToolAllowed(DirModes[AxisIndex], AllowedTransforms))
|
|
{
|
|
NewTrackTool = DirModes[AxisIndex];
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
}
|
|
}
|
|
|
|
lcPiece* Piece = (lcPiece*)Focus;
|
|
|
|
if (ControlPointIndex != -1 && Piece->mPieceInfo->GetSynthInfo() && Piece->mPieceInfo->GetSynthInfo()->IsCurve())
|
|
{
|
|
float Strength = Piece->GetControlPoints()[ControlPointIndex].Scale;
|
|
const float ScaleStart = (2.0f - OverlayScaleRadius) * OverlayScale + Strength;
|
|
const float ScaleEnd = (2.0f + OverlayScaleRadius) * OverlayScale + Strength;
|
|
|
|
if (AxisIndex == 1 && fabs(Proj1) < OverlayScaleRadius * OverlayScale)
|
|
{
|
|
if (Proj2 > ScaleStart && Proj2 < ScaleEnd)
|
|
{
|
|
if (IsTrackToolAllowed(lcTrackTool::ScalePlus, AllowedTransforms))
|
|
{
|
|
NewTrackTool = lcTrackTool::ScalePlus;
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
}
|
|
}
|
|
else if (Proj2 < -ScaleStart && Proj2 > -ScaleEnd)
|
|
{
|
|
if (IsTrackToolAllowed(lcTrackTool::ScaleMinus, AllowedTransforms))
|
|
{
|
|
NewTrackTool = lcTrackTool::ScaleMinus;
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
}
|
|
}
|
|
}
|
|
else if (AxisIndex == 2 && fabs(Proj2) < OverlayScaleRadius * OverlayScale)
|
|
{
|
|
if (Proj1 > ScaleStart && Proj1 < ScaleEnd)
|
|
{
|
|
if (IsTrackToolAllowed(lcTrackTool::ScalePlus, AllowedTransforms))
|
|
{
|
|
NewTrackTool = lcTrackTool::ScalePlus;
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
}
|
|
}
|
|
else if (Proj1 < -ScaleStart && Proj1 > -ScaleEnd)
|
|
{
|
|
if (IsTrackToolAllowed(lcTrackTool::ScaleMinus, AllowedTransforms))
|
|
{
|
|
NewTrackTool = lcTrackTool::ScaleMinus;
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Focus && Focus->IsPiece())
|
|
{
|
|
lcPiece* Piece = (lcPiece*)Focus;
|
|
const lcTrainTrackInfo* TrainTrackInfo = Piece->mPieceInfo->GetTrainTrackInfo();
|
|
|
|
if (TrainTrackInfo)
|
|
{
|
|
ActiveModel->UpdateTrainTrackConnections(Piece);
|
|
|
|
const std::vector<lcTrainTrackConnection>& Connections = TrainTrackInfo->GetConnections();
|
|
|
|
for (quint32 ConnectionIndex = 0; ConnectionIndex < Connections.size(); ConnectionIndex++)
|
|
{
|
|
if (Piece->IsTrainTrackConnected(ConnectionIndex))
|
|
continue;
|
|
|
|
const lcMatrix44& Transform = Connections[ConnectionIndex].Transform;
|
|
lcVector3 Verts[static_cast<int>(lcTrainTrackType::Count)];
|
|
int NumVerts = 0;
|
|
|
|
Verts[NumVerts++] = (Transform.GetTranslation() + lcVector3(Transform[0]) * 100) / 1;
|
|
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 60)) * 100) / 1;
|
|
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -60)) * 100) / 1;
|
|
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * 30)) * 100) / 1;
|
|
Verts[NumVerts++] = (Transform.GetTranslation() + lcMul31(lcVector3(Transform[0]), lcMatrix44RotationZ(LC_DTOR * -30)) * 100) / 1;
|
|
|
|
for (int VertexIndex = 0; VertexIndex < NumVerts; VertexIndex++)
|
|
{
|
|
Verts[VertexIndex] = lcMul31(Verts[VertexIndex], WorldMatrix);
|
|
|
|
float IntersectionDistance = lcRayPointDistance(Verts[VertexIndex], Start, End);
|
|
|
|
if (IntersectionDistance < 40)
|
|
{
|
|
if (IntersectionDistance > ClosestIntersectionDistance)
|
|
continue;
|
|
|
|
NewTrackTool = lcTrackTool::Insert;
|
|
ClosestIntersectionDistance = IntersectionDistance;
|
|
NewTrackSection = ConnectionIndex | (VertexIndex << 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
lcObjectRayTest ObjectRayTest;
|
|
|
|
ObjectRayTest.PiecesOnly = true;
|
|
ObjectRayTest.IgnoreSelected = false;
|
|
ObjectRayTest.ViewCamera = mView->GetCamera();
|
|
ObjectRayTest.Start = StartEnd[0];
|
|
ObjectRayTest.End = StartEnd[1];
|
|
|
|
Piece->RayTestConnectedTrainTracks(ObjectRayTest);
|
|
|
|
if (ObjectRayTest.Distance < ClosestIntersectionDistance && ObjectRayTest.ObjectSection.Section >= LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST)
|
|
{
|
|
NewTrackTool = lcTrackTool::RotateTrainTrack;
|
|
ClosestIntersectionDistance = ObjectRayTest.Distance;
|
|
NewTrackSection = ObjectRayTest.ObjectSection.Section - LC_PIECE_SECTION_TRAIN_TRACK_CONNECTION_FIRST;
|
|
}
|
|
}
|
|
}
|
|
|
|
return { NewTrackTool, NewTrackSection };
|
|
}
|
|
|
|
lcTrackTool lcViewManipulator::UpdateRotate()
|
|
{
|
|
const lcModel* ActiveModel = mView->GetActiveModel();
|
|
const float OverlayScale = mView->GetOverlayScale();
|
|
const float OverlayRotateRadius = 2.0f;
|
|
|
|
lcVector3 OverlayCenter;
|
|
lcMatrix33 RelativeRotation;
|
|
|
|
if (!ActiveModel->GetMoveRotateTransform(OverlayCenter, RelativeRotation))
|
|
return lcTrackTool::RotateXYZ;
|
|
|
|
lcMatrix44 WorldMatrix = lcMatrix44(RelativeRotation, OverlayCenter);
|
|
|
|
if (ActiveModel != mView->GetModel())
|
|
WorldMatrix = lcMul(WorldMatrix, mView->GetActiveSubmodelTransform());
|
|
OverlayCenter = WorldMatrix.GetTranslation();
|
|
|
|
const int x = mView->GetMouseX();
|
|
const int y = mView->GetMouseY();
|
|
lcVector3 StartEnd[2] = { lcVector3((float)x, (float)y, 0.0f), lcVector3((float)x, (float)y, 1.0f) };
|
|
mView->UnprojectPoints(StartEnd, 2);
|
|
|
|
lcVector3 Intersection;
|
|
|
|
if (lcSphereRayIntersection(OverlayCenter, OverlayRotateRadius * OverlayScale, StartEnd[0], StartEnd[1], Intersection))
|
|
{
|
|
const lcVector3 LocalIntersection = lcMul(Intersection - OverlayCenter, lcMatrix33AffineInverse(RelativeRotation));
|
|
const float Epsilon = 0.25f * OverlayScale;
|
|
const float dx = fabsf(LocalIntersection[0]);
|
|
const float dy = fabsf(LocalIntersection[1]);
|
|
const float dz = fabsf(LocalIntersection[2]);
|
|
|
|
if (dx < dy)
|
|
{
|
|
if (dx < dz)
|
|
{
|
|
if (dx < Epsilon)
|
|
return lcTrackTool::RotateX;
|
|
}
|
|
else
|
|
{
|
|
if (dz < Epsilon)
|
|
return lcTrackTool::RotateZ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dy < dz)
|
|
{
|
|
if (dy < Epsilon)
|
|
return lcTrackTool::RotateY;
|
|
}
|
|
else
|
|
{
|
|
if (dz < Epsilon)
|
|
return lcTrackTool::RotateZ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return lcTrackTool::RotateXYZ;
|
|
}
|