Merged View and lcGLWidget.

This commit is contained in:
Leonardo Zide 2020-12-25 10:37:59 -08:00
parent 56daed4182
commit 620ac457e5
10 changed files with 929 additions and 969 deletions

View file

@ -1134,5 +1134,5 @@ void lcApplication::ShowPreferencesDialog()
*/
gMainWindow->SetShadingMode(Options.Preferences.mShadingMode);
lcGLWidget::UpdateAllViews();
View::UpdateAllViews();
}

View file

@ -75,7 +75,7 @@ class lcMatrix33;
class lcMatrix44;
class lcViewWidget;
class lcGLWidget;
class lcView;
class lcContext;
class lcMesh;
struct lcMeshSection;

View file

@ -1,676 +0,0 @@
#include "lc_global.h"
#include "lc_glwidget.h"
#include "lc_application.h"
#include "lc_context.h"
#include "piece.h"
#include "camera.h"
#include "pieceinf.h"
#include "texfont.h"
#include "lc_model.h"
#include "lc_scene.h"
#include "lc_viewsphere.h"
lcGLWidget* lcGLWidget::mLastFocusedView;
std::vector<lcGLWidget*> lcGLWidget::mViews;
lcGLWidget::lcGLWidget(lcViewType ViewType, lcModel* Model)
: mScene(new lcScene()), mModel(Model), mViewType(ViewType)
{
mContext = new lcContext();
mViews.push_back(this);
}
lcGLWidget::~lcGLWidget()
{
mViews.erase(std::find(mViews.begin(), mViews.end(), this));
if (mLastFocusedView == this)
mLastFocusedView = nullptr;
if (mDeleteContext)
delete mContext;
}
void lcGLWidget::UpdateProjectViews(const Project* Project)
{
for (lcGLWidget* View : mViews)
{
const lcModel* ViewModel = View->GetActiveModel();
if (ViewModel->GetProject() == Project)
View->Redraw();
}
}
void lcGLWidget::UpdateAllViews()
{
for (lcGLWidget* View : mViews)
View->Redraw();
}
lcModel* lcGLWidget::GetActiveModel() const
{
return !mActiveSubmodelInstance ? mModel : mActiveSubmodelInstance->mPieceInfo->GetModel();
}
void lcGLWidget::SetFocus(bool Focus)
{
if (Focus)
{
mLastFocusedView = this;
emit FocusReceived();
}
}
void lcGLWidget::SetMousePosition(int MouseX, int MouseY)
{
mMouseX = MouseX;
mMouseY = MouseY;
}
void lcGLWidget::SetMouseModifiers(Qt::KeyboardModifiers MouseModifiers)
{
mMouseModifiers = MouseModifiers;
}
void lcGLWidget::SetContext(lcContext* Context)
{
if (mDeleteContext)
delete mContext;
mContext = Context;
mDeleteContext = false;
}
void lcGLWidget::MakeCurrent()
{
mWidget->makeCurrent();
}
void lcGLWidget::Redraw()
{
mWidget->update();
}
lcCursor lcGLWidget::GetCursor() const
{
if (mTrackButton != lcTrackButton::None)
return lcCursor::Hidden;
if (mTrackTool == lcTrackTool::Select)
{
if (mMouseModifiers & Qt::ControlModifier)
return lcCursor::SelectAdd;
if (mMouseModifiers & Qt::ShiftModifier)
return lcCursor::SelectRemove;
}
constexpr lcCursor CursorFromTrackTool[] =
{
lcCursor::Select, // lcTrackTool::None
lcCursor::Brick, // lcTrackTool::Insert
lcCursor::Light, // lcTrackTool::PointLight
lcCursor::Spotlight, // lcTrackTool::SpotLight
lcCursor::Camera, // lcTrackTool::Camera
lcCursor::Select, // lcTrackTool::Select
lcCursor::Move, // lcTrackTool::MoveX
lcCursor::Move, // lcTrackTool::MoveY
lcCursor::Move, // lcTrackTool::MoveZ
lcCursor::Move, // lcTrackTool::MoveXY
lcCursor::Move, // lcTrackTool::MoveXZ
lcCursor::Move, // lcTrackTool::MoveYZ
lcCursor::Move, // lcTrackTool::MoveXYZ
lcCursor::Rotate, // lcTrackTool::RotateX
lcCursor::Rotate, // lcTrackTool::RotateY
lcCursor::Rotate, // lcTrackTool::RotateZ
lcCursor::Rotate, // lcTrackTool::RotateXY
lcCursor::Rotate, // lcTrackTool::RotateXYZ
lcCursor::Move, // lcTrackTool::ScalePlus
lcCursor::Move, // lcTrackTool::ScaleMinus
lcCursor::Delete, // lcTrackTool::Eraser
lcCursor::Paint, // lcTrackTool::Paint
lcCursor::ColorPicker, // lcTrackTool::ColorPicker
lcCursor::Zoom, // lcTrackTool::Zoom
lcCursor::Pan, // lcTrackTool::Pan
lcCursor::RotateX, // lcTrackTool::OrbitX
lcCursor::RotateY, // lcTrackTool::OrbitY
lcCursor::RotateView, // lcTrackTool::OrbitXY
lcCursor::Roll, // lcTrackTool::Roll
lcCursor::ZoomRegion // lcTrackTool::ZoomRegion
};
LC_ARRAY_SIZE_CHECK(CursorFromTrackTool, lcTrackTool::Count);
if (mTrackTool >= lcTrackTool::None && mTrackTool < lcTrackTool::Count)
return CursorFromTrackTool[static_cast<int>(mTrackTool)];
return lcCursor::Select;
}
void lcGLWidget::SetCursor(lcCursor CursorType)
{
if (mCursor == CursorType)
return;
struct lcCursorInfo
{
int x, y;
const char* Name;
};
constexpr lcCursorInfo Cursors[] =
{
{ 0, 0, "" }, // lcCursor::Hidden
{ 0, 0, "" }, // lcCursor::Default
{ 8, 3, ":/resources/cursor_insert" }, // lcCursor::Brick
{ 15, 15, ":/resources/cursor_light" }, // lcCursor::Light
{ 7, 10, ":/resources/cursor_spotlight" }, // lcCursor::Spotlight
{ 15, 9, ":/resources/cursor_camera" }, // lcCursor::Camera
{ 0, 2, ":/resources/cursor_select" }, // lcCursor::Select
{ 0, 2, ":/resources/cursor_select_add" }, // lcCursor::SelectAdd
{ 0, 2, ":/resources/cursor_select_remove" }, // lcCursor::SelectRemove
{ 15, 15, ":/resources/cursor_move" }, // lcCursor::Move
{ 15, 15, ":/resources/cursor_rotate" }, // lcCursor::Rotate
{ 15, 15, ":/resources/cursor_rotatex" }, // lcCursor::RotateX
{ 15, 15, ":/resources/cursor_rotatey" }, // lcCursor::RotateY
{ 0, 10, ":/resources/cursor_delete" }, // lcCursor::Delete
{ 14, 14, ":/resources/cursor_paint" }, // lcCursor::Paint
{ 1, 13, ":/resources/cursor_color_picker" }, // lcCursor::ColorPicker
{ 15, 15, ":/resources/cursor_zoom" }, // lcCursor::Zoom
{ 9, 9, ":/resources/cursor_zoom_region" }, // lcCursor::ZoomRegion
{ 15, 15, ":/resources/cursor_pan" }, // lcCursor::Pan
{ 15, 15, ":/resources/cursor_roll" }, // lcCursor::Roll
{ 15, 15, ":/resources/cursor_rotate_view" }, // lcCursor::RotateView
};
LC_ARRAY_SIZE_CHECK(Cursors, lcCursor::Count);
if (CursorType == lcCursor::Hidden)
{
mWidget->setCursor(Qt::BlankCursor);
mCursor = CursorType;
}
else if (CursorType >= lcCursor::First && CursorType < lcCursor::Count)
{
const lcCursorInfo& Cursor = Cursors[static_cast<int>(CursorType)];
mWidget->setCursor(QCursor(QPixmap(Cursor.Name), Cursor.x, Cursor.y));
mCursor = CursorType;
}
else
{
mWidget->unsetCursor();
mCursor = lcCursor::Default;
}
}
void lcGLWidget::UpdateCursor()
{
SetCursor(GetCursor());
}
lcTool lcGLWidget::GetCurrentTool() const
{
constexpr lcTool ToolFromTrackTool[] =
{
lcTool::Select, // lcTrackTool::None
lcTool::Insert, // lcTrackTool::Insert
lcTool::Light, // lcTrackTool::PointLight
lcTool::SpotLight, // lcTrackTool::SpotLight
lcTool::Camera, // lcTrackTool::Camera
lcTool::Select, // lcTrackTool::Select
lcTool::Move, // lcTrackTool::MoveX
lcTool::Move, // lcTrackTool::MoveY
lcTool::Move, // lcTrackTool::MoveZ
lcTool::Move, // lcTrackTool::MoveXY
lcTool::Move, // lcTrackTool::MoveXZ
lcTool::Move, // lcTrackTool::MoveYZ
lcTool::Move, // lcTrackTool::MoveXYZ
lcTool::Rotate, // lcTrackTool::RotateX
lcTool::Rotate, // lcTrackTool::RotateY
lcTool::Rotate, // lcTrackTool::RotateZ
lcTool::Rotate, // lcTrackTool::RotateXY
lcTool::Rotate, // lcTrackTool::RotateXYZ
lcTool::Move, // lcTrackTool::ScalePlus
lcTool::Move, // lcTrackTool::ScaleMinus
lcTool::Eraser, // lcTrackTool::Eraser
lcTool::Paint, // lcTrackTool::Paint
lcTool::ColorPicker, // lcTrackTool::ColorPicker
lcTool::Zoom, // lcTrackTool::Zoom
lcTool::Pan, // lcTrackTool::Pan
lcTool::RotateView, // lcTrackTool::OrbitX
lcTool::RotateView, // lcTrackTool::OrbitY
lcTool::RotateView, // lcTrackTool::OrbitXY
lcTool::Roll, // lcTrackTool::Roll
lcTool::ZoomRegion // lcTrackTool::ZoomRegion
};
LC_ARRAY_SIZE_CHECK(ToolFromTrackTool, lcTrackTool::Count);
if (mTrackTool >= lcTrackTool::None && mTrackTool < lcTrackTool::Count)
return ToolFromTrackTool[static_cast<int>(mTrackTool)];
return lcTool::Select;
}
lcMatrix44 lcGLWidget::GetProjectionMatrix() const
{
float AspectRatio = (float)mWidth / (float)mHeight;
if (mCamera->IsOrtho())
{
float OrthoHeight = mCamera->GetOrthoHeight() / 2.0f;
float OrthoWidth = OrthoHeight * AspectRatio;
return lcMatrix44Ortho(-OrthoWidth, OrthoWidth, -OrthoHeight, OrthoHeight, mCamera->m_zNear, mCamera->m_zFar * 4);
}
else
return lcMatrix44Perspective(mCamera->m_fovy, AspectRatio, mCamera->m_zNear, mCamera->m_zFar);
}
lcVector3 lcGLWidget::ProjectPoint(const lcVector3& Point) const
{
int Viewport[4] = { 0, 0, mWidth, mHeight };
return lcProjectPoint(Point, mCamera->mWorldView, GetProjectionMatrix(), Viewport);
}
lcVector3 lcGLWidget::UnprojectPoint(const lcVector3& Point) const
{
int Viewport[4] = { 0, 0, mWidth, mHeight };
return lcUnprojectPoint(Point, mCamera->mWorldView, GetProjectionMatrix(), Viewport);
}
void lcGLWidget::UnprojectPoints(lcVector3* Points, int NumPoints) const
{
int Viewport[4] = { 0, 0, mWidth, mHeight };
lcUnprojectPoints(Points, NumPoints, mCamera->mWorldView, GetProjectionMatrix(), Viewport);
}
void lcGLWidget::ZoomExtents()
{
lcModel* ActiveModel = GetActiveModel();
if (ActiveModel)
ActiveModel->ZoomExtents(mCamera, (float)mWidth / (float)mHeight);
}
void lcGLWidget::SetViewpoint(lcViewpoint Viewpoint)
{
if (!mCamera || !mCamera->IsSimple())
{
lcCamera* OldCamera = mCamera;
mCamera = new lcCamera(true);
if (OldCamera)
mCamera->CopySettings(OldCamera);
}
mCamera->SetViewpoint(Viewpoint);
ZoomExtents();
Redraw();
emit CameraChanged();
}
void lcGLWidget::SetViewpoint(const lcVector3& Position)
{
if (!mCamera || !mCamera->IsSimple())
{
lcCamera* OldCamera = mCamera;
mCamera = new lcCamera(true);
if (OldCamera)
mCamera->CopySettings(OldCamera);
}
mCamera->SetViewpoint(Position);
ZoomExtents();
Redraw();
emit CameraChanged();
}
void lcGLWidget::SetViewpoint(const lcVector3& Position, const lcVector3& Target, const lcVector3& Up)
{
if (!mCamera || !mCamera->IsSimple())
{
lcCamera* OldCamera = mCamera;
mCamera = new lcCamera(true);
if (OldCamera)
mCamera->CopySettings(OldCamera);
}
mCamera->SetViewpoint(Position, Target, Up);
Redraw();
emit CameraChanged();
}
void lcGLWidget::SetCameraAngles(float Latitude, float Longitude)
{
if (!mCamera || !mCamera->IsSimple())
{
lcCamera* OldCamera = mCamera;
mCamera = new lcCamera(true);
if (OldCamera)
mCamera->CopySettings(OldCamera);
}
mCamera->SetAngles(Latitude, Longitude, 1.0f);
ZoomExtents();
Redraw();
}
void lcGLWidget::SetDefaultCamera()
{
if (!mCamera || !mCamera->IsSimple())
mCamera = new lcCamera(true);
mCamera->SetViewpoint(lcViewpoint::Home);
emit CameraChanged();
}
void lcGLWidget::SetCamera(lcCamera* Camera, bool ForceCopy)
{
if (Camera->IsSimple() || ForceCopy)
{
if (!mCamera || !mCamera->IsSimple())
mCamera = new lcCamera(true);
mCamera->CopyPosition(Camera);
}
else
{
if (mCamera && mCamera->IsSimple())
delete mCamera;
mCamera = Camera;
}
}
void lcGLWidget::SetCamera(const QString& CameraName)
{
const lcArray<lcCamera*>& Cameras = mModel->GetCameras();
for (int CameraIdx = 0; CameraIdx < Cameras.GetSize(); CameraIdx++)
{
if (CameraName.compare(Cameras[CameraIdx]->GetName(), Qt::CaseInsensitive) == 0)
{
SetCameraIndex(CameraIdx);
return;
}
}
}
void lcGLWidget::SetCameraIndex(int Index)
{
const lcArray<lcCamera*>& Cameras = mModel->GetCameras();
if (Index >= Cameras.GetSize())
return;
lcCamera* Camera = Cameras[Index];
SetCamera(Camera, false);
emit CameraChanged();
Redraw();
}
void lcGLWidget::StartTracking(lcTrackButton TrackButton)
{
mTrackButton = TrackButton;
mTrackUpdated = false;
mMouseDownX = mMouseX;
mMouseDownY = mMouseY;
lcTool Tool = GetCurrentTool();
lcModel* ActiveModel = GetActiveModel();
switch (Tool)
{
case lcTool::Insert:
case lcTool::Light:
break;
case lcTool::SpotLight:
{
lcVector3 Position = GetCameraLightInsertPosition();
lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f);
ActiveModel->BeginSpotLightTool(Position, Target);
}
break;
case lcTool::Camera:
{
lcVector3 Position = GetCameraLightInsertPosition();
lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f);
ActiveModel->BeginCameraTool(Position, Target);
}
break;
case lcTool::Select:
break;
case lcTool::Move:
case lcTool::Rotate:
ActiveModel->BeginMouseTool();
break;
case lcTool::Eraser:
case lcTool::Paint:
case lcTool::ColorPicker:
break;
case lcTool::Zoom:
case lcTool::Pan:
case lcTool::RotateView:
case lcTool::Roll:
ActiveModel->BeginMouseTool();
break;
case lcTool::ZoomRegion:
break;
case lcTool::Count:
break;
}
UpdateCursor();
}
lcVector3 lcGLWidget::GetCameraLightInsertPosition() const
{
lcModel* ActiveModel = GetActiveModel();
std::array<lcVector3, 2> ClickPoints = { { lcVector3((float)mMouseX, (float)mMouseY, 0.0f), lcVector3((float)mMouseX, (float)mMouseY, 1.0f) } };
UnprojectPoints(ClickPoints.data(), 2);
if (ActiveModel != mModel)
{
lcMatrix44 InverseMatrix = lcMatrix44AffineInverse(mActiveSubmodelTransform);
for (lcVector3& Point : ClickPoints)
Point = lcMul31(Point, InverseMatrix);
}
lcVector3 Min, Max;
lcVector3 Center;
if (ActiveModel->GetPiecesBoundingBox(Min, Max))
Center = (Min + Max) / 2.0f;
else
Center = lcVector3(0.0f, 0.0f, 0.0f);
return lcRayPointClosestPoint(Center, ClickPoints[0], ClickPoints[1]);
}
void lcGLWidget::OnMouseWheel(float Direction)
{
mModel->Zoom(mCamera, (int)(((mMouseModifiers & Qt::ControlModifier) ? 100 : 10) * Direction));
}
void lcGLWidget::DrawBackground() const
{
const lcPreferences& Preferences = lcGetPreferences();
if (!Preferences.mBackgroundGradient)
{
lcVector3 BackgroundColor = lcVector3FromColor(Preferences.mBackgroundSolidColor);
glClearColor(BackgroundColor[0], BackgroundColor[1], BackgroundColor[2], 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
return;
}
lcContext* Context = mContext;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Context->SetDepthWrite(false);
glDisable(GL_DEPTH_TEST);
float ViewWidth = (float)mWidth;
float ViewHeight = (float)mHeight;
Context->SetWorldMatrix(lcMatrix44Identity());
Context->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
Context->SetProjectionMatrix(lcMatrix44Ortho(0.0f, ViewWidth, 0.0f, ViewHeight, -1.0f, 1.0f));
Context->SetSmoothShading(true);
const lcVector3 Color1 = lcVector3FromColor(Preferences.mBackgroundGradientColorTop);
const lcVector3 Color2 = lcVector3FromColor(Preferences.mBackgroundGradientColorBottom);
float Verts[] =
{
ViewWidth, ViewHeight, Color1[0], Color1[1], Color1[2], 1.0f,
0.0f, ViewHeight, Color1[0], Color1[1], Color1[2], 1.0f,
0.0f, 0.0f, Color2[0], Color2[1], Color2[2], 1.0f,
ViewWidth, 0.0f, Color2[0], Color2[1], Color2[2], 1.0f
};
Context->SetMaterial(lcMaterialType::UnlitVertexColor);
Context->SetVertexBufferPointer(Verts);
Context->SetVertexFormat(0, 2, 0, 0, 4, false);
Context->DrawPrimitives(GL_TRIANGLE_FAN, 0, 4);
Context->SetSmoothShading(false);
glEnable(GL_DEPTH_TEST);
Context->SetDepthWrite(true);
}
void lcGLWidget::DrawViewport() const
{
mContext->SetWorldMatrix(lcMatrix44Identity());
mContext->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f));
mContext->SetDepthWrite(false);
glDisable(GL_DEPTH_TEST);
mContext->SetMaterial(lcMaterialType::UnlitColor);
if (mLastFocusedView == this)
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mActiveViewColor));
else
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mInactiveViewColor));
float Verts[8] = { 0.0f, 0.0f, mWidth - 1.0f, 0.0f, mWidth - 1.0f, mHeight - 1.0f, 0.0f, mHeight - 1.0f };
mContext->SetVertexBufferPointer(Verts);
mContext->SetVertexFormatPosition(2);
mContext->DrawPrimitives(GL_LINE_LOOP, 0, 4);
QString CameraName = mCamera->GetName();
if (!CameraName.isEmpty())
{
mContext->SetMaterial(lcMaterialType::UnlitTextureModulate);
mContext->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
mContext->BindTexture2D(gTexFont.GetTexture());
glEnable(GL_BLEND);
gTexFont.PrintText(mContext, 3.0f, (float)mHeight - 1.0f - 6.0f, 0.0f, CameraName.toLatin1().constData());
glDisable(GL_BLEND);
}
mContext->SetDepthWrite(true);
glEnable(GL_DEPTH_TEST);
}
void lcGLWidget::DrawAxes() const
{
// glClear(GL_DEPTH_BUFFER_BIT);
const float Verts[28 * 3] =
{
0.00f, 0.00f, 0.00f, 20.00f, 0.00f, 0.00f, 12.00f, 3.00f, 0.00f, 12.00f, 2.12f, 2.12f,
12.00f, 0.00f, 3.00f, 12.00f, -2.12f, 2.12f, 12.00f, -3.00f, 0.00f, 12.00f, -2.12f, -2.12f,
12.00f, 0.00f, -3.00f, 12.00f, 2.12f, -2.12f, 0.00f, 20.00f, 0.00f, 3.00f, 12.00f, 0.00f,
2.12f, 12.00f, 2.12f, 0.00f, 12.00f, 3.00f, -2.12f, 12.00f, 2.12f, -3.00f, 12.00f, 0.00f,
-2.12f, 12.00f, -2.12f, 0.00f, 12.00f, -3.00f, 2.12f, 12.00f, -2.12f, 0.00f, 0.00f, 20.00f,
0.00f, 3.00f, 12.00f, 2.12f, 2.12f, 12.00f, 3.00f, 0.00f, 12.00f, 2.12f, -2.12f, 12.00f,
0.00f, -3.00f, 12.00f, -2.12f, -2.12f, 12.00f, -3.00f, 0.00f, 12.00f, -2.12f, 2.12f, 12.00f,
};
const GLushort Indices[78] =
{
0, 1, 0, 10, 0, 19,
1, 2, 3, 1, 3, 4, 1, 4, 5, 1, 5, 6, 1, 6, 7, 1, 7, 8, 1, 8, 9, 1, 9, 2,
10, 11, 12, 10, 12, 13, 10, 13, 14, 10, 14, 15, 10, 15, 16, 10, 16, 17, 10, 17, 18, 10, 18, 11,
19, 20, 21, 19, 21, 22, 19, 22, 23, 19, 23, 24, 19, 24, 25, 19, 25, 26, 19, 26, 27, 19, 27, 20
};
lcMatrix44 TranslationMatrix = lcMatrix44Translation(lcVector3(30.375f, 30.375f, 0.0f));
lcMatrix44 WorldViewMatrix = mCamera->mWorldView;
WorldViewMatrix.SetTranslation(lcVector3(0, 0, 0));
mContext->SetMaterial(lcMaterialType::UnlitColor);
mContext->SetWorldMatrix(lcMatrix44Identity());
mContext->SetViewMatrix(lcMul(WorldViewMatrix, TranslationMatrix));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0, mWidth, 0, mHeight, -50, 50));
mContext->SetVertexBufferPointer(Verts);
mContext->SetVertexFormatPosition(3);
mContext->SetIndexBufferPointer(Indices);
mContext->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_LINES, 6, GL_UNSIGNED_SHORT, 0);
mContext->SetColor(0.8f, 0.0f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, 6 * 2);
mContext->SetColor(0.0f, 0.8f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, (6 + 24) * 2);
mContext->SetColor(0.0f, 0.0f, 0.8f, 1.0f);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, (6 + 48) * 2);
mContext->SetMaterial(lcMaterialType::UnlitTextureModulate);
mContext->SetViewMatrix(TranslationMatrix);
mContext->BindTexture2D(gTexFont.GetTexture());
glEnable(GL_BLEND);
float TextBuffer[6 * 5 * 3];
lcVector3 PosX = lcMul30(lcVector3(25.0f, 0.0f, 0.0f), WorldViewMatrix);
gTexFont.GetGlyphTriangles(PosX.x, PosX.y, PosX.z, 'X', TextBuffer);
lcVector3 PosY = lcMul30(lcVector3(0.0f, 25.0f, 0.0f), WorldViewMatrix);
gTexFont.GetGlyphTriangles(PosY.x, PosY.y, PosY.z, 'Y', TextBuffer + 5 * 6);
lcVector3 PosZ = lcMul30(lcVector3(0.0f, 0.0f, 25.0f), WorldViewMatrix);
gTexFont.GetGlyphTriangles(PosZ.x, PosZ.y, PosZ.z, 'Z', TextBuffer + 5 * 6 * 2);
mContext->SetVertexBufferPointer(TextBuffer);
mContext->SetVertexFormat(0, 3, 0, 2, 0, false);
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mAxesColor));
mContext->DrawPrimitives(GL_TRIANGLES, 0, 6 * 3);
glDisable(GL_BLEND);
}

View file

@ -1,249 +0,0 @@
#pragma once
#include "lc_commands.h"
#include "lc_math.h"
enum class lcDragState
{
None,
Piece,
Color
};
enum class lcCursor
{
First,
Hidden = First,
Default,
Brick,
Light,
Spotlight,
Camera,
Select,
SelectAdd,
SelectRemove,
Move,
Rotate,
RotateX,
RotateY,
Delete,
Paint,
ColorPicker,
Zoom,
ZoomRegion,
Pan,
Roll,
RotateView,
Count
};
enum class lcTrackButton
{
None,
Left,
Middle,
Right
};
enum class lcTrackTool
{
None,
Insert,
PointLight,
SpotLight,
Camera,
Select,
MoveX,
MoveY,
MoveZ,
MoveXY,
MoveXZ,
MoveYZ,
MoveXYZ,
RotateX,
RotateY,
RotateZ,
RotateXY,
RotateXYZ,
ScalePlus,
ScaleMinus,
Eraser,
Paint,
ColorPicker,
Zoom,
Pan,
OrbitX,
OrbitY,
OrbitXY,
Roll,
ZoomRegion,
Count
};
enum class lcViewType
{
View,
Preview,
Minifig,
Count
};
class lcGLWidget : public QObject
{
Q_OBJECT
public:
lcGLWidget(lcViewType ViewType, lcModel* Model);
virtual ~lcGLWidget();
lcGLWidget(const lcGLWidget&) = delete;
lcGLWidget& operator=(const lcGLWidget&) = delete;
static void UpdateProjectViews(const Project* Project);
static void UpdateAllViews();
lcModel* GetActiveModel() const;
lcViewType GetViewType() const
{
return mViewType;
}
lcCamera* GetCamera() const
{
return mCamera;
}
bool IsLastFocused() const
{
return mLastFocusedView == this;
}
bool IsTracking() const
{
return mTrackButton != lcTrackButton::None;
}
int GetWidth() const
{
return mWidth;
}
int GetHeight() const
{
return mHeight;
}
void SetSize(int Width, int Height)
{
mWidth = Width;
mHeight = Height;
}
QGLWidget* GetWidget() const
{
return mWidget;
}
void SetWidget(QGLWidget* Widget)
{
mWidget = Widget;
}
int GetMouseX() const
{
return mMouseX;
}
int GetMouseY() const
{
return mMouseY;
}
void SetFocus(bool Focus);
void SetMousePosition(int MouseX, int MouseY);
void SetMouseModifiers(Qt::KeyboardModifiers MouseModifiers);
void SetContext(lcContext* Context);
void MakeCurrent();
void Redraw();
void UpdateCursor();
lcVector3 ProjectPoint(const lcVector3& Point) const;
lcVector3 UnprojectPoint(const lcVector3& Point) const;
void UnprojectPoints(lcVector3* Points, int NumPoints) const;
lcMatrix44 GetProjectionMatrix() const;
void ZoomExtents();
void SetViewpoint(lcViewpoint Viewpoint);
void SetViewpoint(const lcVector3& Position);
void SetViewpoint(const lcVector3& Position, const lcVector3& Target, const lcVector3& Up);
void SetCameraAngles(float Latitude, float Longitude);
void SetDefaultCamera();
void SetCamera(lcCamera* Camera, bool ForceCopy);
void SetCamera(const QString& CameraName);
void SetCameraIndex(int Index);
void DrawBackground() const;
void DrawViewport() const;
void DrawAxes() const;
virtual void OnDraw() { }
virtual void OnLeftButtonDown() { }
virtual void OnLeftButtonUp() { }
virtual void OnLeftButtonDoubleClick() { }
virtual void OnMiddleButtonDown() { }
virtual void OnMiddleButtonUp() { }
virtual void OnRightButtonDown() { }
virtual void OnRightButtonUp() { }
virtual void OnBackButtonDown() { }
virtual void OnBackButtonUp() { }
virtual void OnForwardButtonDown() { }
virtual void OnForwardButtonUp() { }
virtual void OnMouseMove() { }
void OnMouseWheel(float Direction);
virtual void BeginDrag(lcDragState DragState) { Q_UNUSED(DragState); }
virtual void EndDrag(bool Accept) { Q_UNUSED(Accept); }
lcContext* mContext = nullptr;
signals:
void FocusReceived();
void CameraChanged();
protected:
lcCursor GetCursor() const;
void SetCursor(lcCursor Cursor);
lcTool GetCurrentTool() const;
void StartTracking(lcTrackButton TrackButton);
lcVector3 GetCameraLightInsertPosition() const;
int mMouseX = 0;
int mMouseY = 0;
int mMouseDownX = 0;
int mMouseDownY = 0;
Qt::KeyboardModifiers mMouseModifiers = Qt::NoModifier;
bool mTrackUpdated = false;
lcTrackTool mTrackTool = lcTrackTool::None;
lcTrackButton mTrackButton = lcTrackButton::None;
lcCursor mCursor = lcCursor::Default;
std::unique_ptr<lcScene> mScene;
std::unique_ptr<lcViewSphere> mViewSphere;
lcModel* mModel = nullptr;
lcPiece* mActiveSubmodelInstance = nullptr;
lcMatrix44 mActiveSubmodelTransform;
lcCamera* mCamera = nullptr;
QGLWidget* mWidget = nullptr;
int mWidth = 1;
int mHeight = 1;
bool mDeleteContext = true;
lcViewType mViewType;
static lcGLWidget* mLastFocusedView;
static std::vector<lcGLWidget*> mViews;
};

View file

@ -1138,7 +1138,7 @@ void lcMainWindow::ProjectFileChanged(const QString& Path)
QByteArray TabLayout = GetTabLayout();
gApplication->SetProject(NewProject);
RestoreTabLayout(TabLayout);
lcGLWidget::UpdateAllViews();
View::UpdateAllViews();
}
}
else
@ -1346,8 +1346,11 @@ void lcMainWindow::ShowPrintDialog()
void lcMainWindow::SetShadingMode(lcShadingMode ShadingMode)
{
lcGetPreferences().mShadingMode = ShadingMode;
UpdateShadingMode();
lcGLWidget::UpdateAllViews();
View::UpdateAllViews();
if (mPartSelectionWidget)
mPartSelectionWidget->Redraw();
}
@ -1355,6 +1358,7 @@ void lcMainWindow::SetShadingMode(lcShadingMode ShadingMode)
void lcMainWindow::SetSelectionMode(lcSelectionMode SelectionMode)
{
mSelectionMode = SelectionMode;
UpdateSelectionMode();
}
@ -1362,28 +1366,28 @@ void lcMainWindow::ToggleViewSphere()
{
lcGetPreferences().mViewSphereEnabled = !lcGetPreferences().mViewSphereEnabled;
lcGLWidget::UpdateAllViews();
View::UpdateAllViews();
}
void lcMainWindow::ToggleAxisIcon()
{
lcGetPreferences().mDrawAxes = !lcGetPreferences().mDrawAxes;
lcGLWidget::UpdateAllViews();
View::UpdateAllViews();
}
void lcMainWindow::ToggleGrid()
{
lcGetPreferences().mGridEnabled = !lcGetPreferences().mGridEnabled;
lcGLWidget::UpdateAllViews();
View::UpdateAllViews();
}
void lcMainWindow::ToggleFadePreviousSteps()
{
lcGetPreferences().mFadeSteps = !lcGetPreferences().mFadeSteps;
lcGLWidget::UpdateAllViews();
View::UpdateAllViews();
}
QByteArray lcMainWindow::GetTabLayout()
@ -1728,7 +1732,7 @@ void lcMainWindow::SetTool(lcTool Tool)
if (Action)
Action->setChecked(true);
lcGLWidget::UpdateAllViews();
View::UpdateAllViews();
}
void lcMainWindow::SetColorIndex(int ColorIndex)
@ -1775,7 +1779,7 @@ void lcMainWindow::SetRelativeTransform(bool RelativeTransform)
{
mRelativeTransform = RelativeTransform;
UpdateLockSnap();
lcGLWidget::UpdateAllViews();
View::UpdateAllViews();
}
void lcMainWindow::SetLocalTransform(bool SelectionTransform)
@ -2180,9 +2184,9 @@ void lcMainWindow::ViewFocusReceived()
void lcMainWindow::ViewCameraChanged()
{
lcGLWidget* View = dynamic_cast<lcGLWidget*>(sender());
View* _View = dynamic_cast<View*>(sender());
if (!View || !View->IsLastFocused())
if (!_View || !_View->IsLastFocused())
return;
UpdateCameraMenu();
@ -2397,7 +2401,7 @@ bool lcMainWindow::OpenProjectFile(const QString& FileName)
{
gApplication->SetProject(NewProject);
AddRecentFile(FileName);
lcGLWidget::UpdateProjectViews(NewProject);
View::UpdateProjectViews(NewProject);
return true;
}
@ -2453,7 +2457,7 @@ void lcMainWindow::ImportLDD()
if (NewProject->ImportLDD(LoadFileName))
{
gApplication->SetProject(NewProject);
lcGLWidget::UpdateProjectViews(NewProject);
View::UpdateProjectViews(NewProject);
}
else
delete NewProject;
@ -2473,7 +2477,7 @@ void lcMainWindow::ImportInventory()
if (NewProject->ImportInventory(Dialog.GetSetInventory(), Dialog.GetSetName(), Dialog.GetSetDescription()))
{
gApplication->SetProject(NewProject);
lcGLWidget::UpdateProjectViews(NewProject);
View::UpdateProjectViews(NewProject);
}
else
delete NewProject;

View file

@ -1,6 +1,5 @@
#include "lc_global.h"
#include "lc_viewwidget.h"
#include "lc_glwidget.h"
#include "lc_glextensions.h"
#include "project.h"
#include "lc_library.h"
@ -19,7 +18,7 @@
static QList<lcViewWidget*> gWidgetList;
lcViewWidget::lcViewWidget(QWidget* Parent, lcGLWidget* View)
lcViewWidget::lcViewWidget(QWidget* Parent, View* View)
: QGLWidget(Parent, gWidgetList.isEmpty() ? nullptr : gWidgetList.first())
{
mWheelAccumulator = 0;
@ -86,7 +85,7 @@ QSize lcViewWidget::sizeHint() const
return mPreferredSize.isEmpty() ? QGLWidget::sizeHint() : mPreferredSize;
}
void lcViewWidget::SetView(lcGLWidget* View)
void lcViewWidget::SetView(View* View)
{
mView = View;

View file

@ -1,19 +1,19 @@
#pragma once
#include <QGLWidget>
class View;
class lcViewWidget : public QGLWidget
{
public:
lcViewWidget(QWidget* Parent, lcGLWidget* View);
lcViewWidget(QWidget* Parent, View* View);
~lcViewWidget();
lcGLWidget* GetView() const
View* GetView() const
{
return mView;
}
void SetView(lcGLWidget* View);
void SetView(View* View);
void SetPreviewPosition(const QRect& ParentRect);
QSize sizeHint() const override;
@ -44,7 +44,7 @@ protected:
void dragMoveEvent(QDragMoveEvent* DragMoveEvent) override;
void dropEvent(QDropEvent* DropEvent) override;
lcGLWidget* mView;
View* mView;
QSize mPreferredSize;
int mWheelAccumulator;
};

View file

@ -12,12 +12,18 @@
#include "lc_context.h"
#include "lc_viewsphere.h"
View* View::mLastFocusedView;
std::vector<View*> View::mViews;
lcVertexBuffer View::mRotateMoveVertexBuffer;
lcIndexBuffer View::mRotateMoveIndexBuffer;
View::View(lcViewType ViewType, lcModel* Model)
: lcGLWidget(ViewType, Model)
: mScene(new lcScene()), mModel(Model), mViewType(ViewType)
{
mContext = new lcContext();
mViews.push_back(this);
mViewSphere = std::unique_ptr<lcViewSphere>(new lcViewSphere(this));
memset(mGridSettings, 0, sizeof(mGridSettings));
@ -40,6 +46,76 @@ View::~View()
if (mCamera && mCamera->IsSimple())
delete mCamera;
mViews.erase(std::find(mViews.begin(), mViews.end(), this));
if (mLastFocusedView == this)
mLastFocusedView = nullptr;
if (mDeleteContext)
delete mContext;
}
void View::UpdateProjectViews(const Project* Project)
{
for (View* View : mViews)
{
const lcModel* ViewModel = View->GetActiveModel();
if (ViewModel->GetProject() == Project)
View->Redraw();
}
}
void View::UpdateAllViews()
{
for (View* View : mViews)
View->Redraw();
}
void View::MakeCurrent()
{
mWidget->makeCurrent();
}
void View::Redraw()
{
mWidget->update();
}
void View::SetContext(lcContext* Context)
{
if (mDeleteContext)
delete mContext;
mContext = Context;
mDeleteContext = false;
}
void View::SetFocus(bool Focus)
{
if (Focus)
{
mLastFocusedView = this;
emit FocusReceived();
}
}
void View::SetMousePosition(int MouseX, int MouseY)
{
mMouseX = MouseX;
mMouseY = MouseY;
}
void View::SetMouseModifiers(Qt::KeyboardModifiers MouseModifiers)
{
mMouseModifiers = MouseModifiers;
}
lcModel* View::GetActiveModel() const
{
return !mActiveSubmodelInstance ? mModel : mActiveSubmodelInstance->mPieceInfo->GetModel();
}
void View::SetTopSubmodelActive()
@ -264,6 +340,39 @@ void View::RemoveCamera()
Redraw();
}
lcVector3 View::ProjectPoint(const lcVector3& Point) const
{
int Viewport[4] = { 0, 0, mWidth, mHeight };
return lcProjectPoint(Point, mCamera->mWorldView, GetProjectionMatrix(), Viewport);
}
lcVector3 View::UnprojectPoint(const lcVector3& Point) const
{
int Viewport[4] = { 0, 0, mWidth, mHeight };
return lcUnprojectPoint(Point, mCamera->mWorldView, GetProjectionMatrix(), Viewport);
}
void View::UnprojectPoints(lcVector3* Points, int NumPoints) const
{
int Viewport[4] = { 0, 0, mWidth, mHeight };
lcUnprojectPoints(Points, NumPoints, mCamera->mWorldView, GetProjectionMatrix(), Viewport);
}
lcMatrix44 View::GetProjectionMatrix() const
{
float AspectRatio = (float)mWidth / (float)mHeight;
if (mCamera->IsOrtho())
{
float OrthoHeight = mCamera->GetOrthoHeight() / 2.0f;
float OrthoWidth = OrthoHeight * AspectRatio;
return lcMatrix44Ortho(-OrthoWidth, OrthoWidth, -OrthoHeight, OrthoHeight, mCamera->m_zNear, mCamera->m_zFar * 4);
}
else
return lcMatrix44Perspective(mCamera->m_fovy, AspectRatio, mCamera->m_zNear, mCamera->m_zFar);
}
lcMatrix44 View::GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, int CurrentTileWidth, int CurrentTileHeight) const
{
int ImageWidth = mRenderImage.width();
@ -458,6 +567,32 @@ lcMatrix44 View::GetPieceInsertPosition(bool IgnoreSelected, PieceInfo* Info) co
return lcMatrix44Translation(UnprojectPoint(lcVector3((float)mMouseX, (float)mMouseY, 0.9f)));
}
lcVector3 View::GetCameraLightInsertPosition() const
{
lcModel* ActiveModel = GetActiveModel();
std::array<lcVector3, 2> ClickPoints = { { lcVector3((float)mMouseX, (float)mMouseY, 0.0f), lcVector3((float)mMouseX, (float)mMouseY, 1.0f) } };
UnprojectPoints(ClickPoints.data(), 2);
if (ActiveModel != mModel)
{
lcMatrix44 InverseMatrix = lcMatrix44AffineInverse(mActiveSubmodelTransform);
for (lcVector3& Point : ClickPoints)
Point = lcMul31(Point, InverseMatrix);
}
lcVector3 Min, Max;
lcVector3 Center;
if (ActiveModel->GetPiecesBoundingBox(Min, Max))
Center = (Min + Max) / 2.0f;
else
Center = lcVector3(0.0f, 0.0f, 0.0f);
return lcRayPointClosestPoint(Center, ClickPoints[0], ClickPoints[1]);
}
void View::GetRayUnderPointer(lcVector3& Start, lcVector3& End) const
{
lcVector3 StartEnd[2] =
@ -756,6 +891,166 @@ void View::OnDraw()
mContext->ClearResources();
}
void View::DrawBackground() const
{
const lcPreferences& Preferences = lcGetPreferences();
if (!Preferences.mBackgroundGradient)
{
lcVector3 BackgroundColor = lcVector3FromColor(Preferences.mBackgroundSolidColor);
glClearColor(BackgroundColor[0], BackgroundColor[1], BackgroundColor[2], 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
return;
}
lcContext* Context = mContext;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Context->SetDepthWrite(false);
glDisable(GL_DEPTH_TEST);
float ViewWidth = (float)mWidth;
float ViewHeight = (float)mHeight;
Context->SetWorldMatrix(lcMatrix44Identity());
Context->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
Context->SetProjectionMatrix(lcMatrix44Ortho(0.0f, ViewWidth, 0.0f, ViewHeight, -1.0f, 1.0f));
Context->SetSmoothShading(true);
const lcVector3 Color1 = lcVector3FromColor(Preferences.mBackgroundGradientColorTop);
const lcVector3 Color2 = lcVector3FromColor(Preferences.mBackgroundGradientColorBottom);
float Verts[] =
{
ViewWidth, ViewHeight, Color1[0], Color1[1], Color1[2], 1.0f,
0.0f, ViewHeight, Color1[0], Color1[1], Color1[2], 1.0f,
0.0f, 0.0f, Color2[0], Color2[1], Color2[2], 1.0f,
ViewWidth, 0.0f, Color2[0], Color2[1], Color2[2], 1.0f
};
Context->SetMaterial(lcMaterialType::UnlitVertexColor);
Context->SetVertexBufferPointer(Verts);
Context->SetVertexFormat(0, 2, 0, 0, 4, false);
Context->DrawPrimitives(GL_TRIANGLE_FAN, 0, 4);
Context->SetSmoothShading(false);
glEnable(GL_DEPTH_TEST);
Context->SetDepthWrite(true);
}
void View::DrawViewport() const
{
mContext->SetWorldMatrix(lcMatrix44Identity());
mContext->SetViewMatrix(lcMatrix44Translation(lcVector3(0.375, 0.375, 0.0)));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f));
mContext->SetDepthWrite(false);
glDisable(GL_DEPTH_TEST);
mContext->SetMaterial(lcMaterialType::UnlitColor);
if (mLastFocusedView == this)
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mActiveViewColor));
else
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mInactiveViewColor));
float Verts[8] = { 0.0f, 0.0f, mWidth - 1.0f, 0.0f, mWidth - 1.0f, mHeight - 1.0f, 0.0f, mHeight - 1.0f };
mContext->SetVertexBufferPointer(Verts);
mContext->SetVertexFormatPosition(2);
mContext->DrawPrimitives(GL_LINE_LOOP, 0, 4);
QString CameraName = mCamera->GetName();
if (!CameraName.isEmpty())
{
mContext->SetMaterial(lcMaterialType::UnlitTextureModulate);
mContext->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
mContext->BindTexture2D(gTexFont.GetTexture());
glEnable(GL_BLEND);
gTexFont.PrintText(mContext, 3.0f, (float)mHeight - 1.0f - 6.0f, 0.0f, CameraName.toLatin1().constData());
glDisable(GL_BLEND);
}
mContext->SetDepthWrite(true);
glEnable(GL_DEPTH_TEST);
}
void View::DrawAxes() const
{
// glClear(GL_DEPTH_BUFFER_BIT);
const float Verts[28 * 3] =
{
0.00f, 0.00f, 0.00f, 20.00f, 0.00f, 0.00f, 12.00f, 3.00f, 0.00f, 12.00f, 2.12f, 2.12f,
12.00f, 0.00f, 3.00f, 12.00f, -2.12f, 2.12f, 12.00f, -3.00f, 0.00f, 12.00f, -2.12f, -2.12f,
12.00f, 0.00f, -3.00f, 12.00f, 2.12f, -2.12f, 0.00f, 20.00f, 0.00f, 3.00f, 12.00f, 0.00f,
2.12f, 12.00f, 2.12f, 0.00f, 12.00f, 3.00f, -2.12f, 12.00f, 2.12f, -3.00f, 12.00f, 0.00f,
-2.12f, 12.00f, -2.12f, 0.00f, 12.00f, -3.00f, 2.12f, 12.00f, -2.12f, 0.00f, 0.00f, 20.00f,
0.00f, 3.00f, 12.00f, 2.12f, 2.12f, 12.00f, 3.00f, 0.00f, 12.00f, 2.12f, -2.12f, 12.00f,
0.00f, -3.00f, 12.00f, -2.12f, -2.12f, 12.00f, -3.00f, 0.00f, 12.00f, -2.12f, 2.12f, 12.00f,
};
const GLushort Indices[78] =
{
0, 1, 0, 10, 0, 19,
1, 2, 3, 1, 3, 4, 1, 4, 5, 1, 5, 6, 1, 6, 7, 1, 7, 8, 1, 8, 9, 1, 9, 2,
10, 11, 12, 10, 12, 13, 10, 13, 14, 10, 14, 15, 10, 15, 16, 10, 16, 17, 10, 17, 18, 10, 18, 11,
19, 20, 21, 19, 21, 22, 19, 22, 23, 19, 23, 24, 19, 24, 25, 19, 25, 26, 19, 26, 27, 19, 27, 20
};
lcMatrix44 TranslationMatrix = lcMatrix44Translation(lcVector3(30.375f, 30.375f, 0.0f));
lcMatrix44 WorldViewMatrix = mCamera->mWorldView;
WorldViewMatrix.SetTranslation(lcVector3(0, 0, 0));
mContext->SetMaterial(lcMaterialType::UnlitColor);
mContext->SetWorldMatrix(lcMatrix44Identity());
mContext->SetViewMatrix(lcMul(WorldViewMatrix, TranslationMatrix));
mContext->SetProjectionMatrix(lcMatrix44Ortho(0, mWidth, 0, mHeight, -50, 50));
mContext->SetVertexBufferPointer(Verts);
mContext->SetVertexFormatPosition(3);
mContext->SetIndexBufferPointer(Indices);
mContext->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_LINES, 6, GL_UNSIGNED_SHORT, 0);
mContext->SetColor(0.8f, 0.0f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, 6 * 2);
mContext->SetColor(0.0f, 0.8f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, (6 + 24) * 2);
mContext->SetColor(0.0f, 0.0f, 0.8f, 1.0f);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, (6 + 48) * 2);
mContext->SetMaterial(lcMaterialType::UnlitTextureModulate);
mContext->SetViewMatrix(TranslationMatrix);
mContext->BindTexture2D(gTexFont.GetTexture());
glEnable(GL_BLEND);
float TextBuffer[6 * 5 * 3];
lcVector3 PosX = lcMul30(lcVector3(25.0f, 0.0f, 0.0f), WorldViewMatrix);
gTexFont.GetGlyphTriangles(PosX.x, PosX.y, PosX.z, 'X', TextBuffer);
lcVector3 PosY = lcMul30(lcVector3(0.0f, 25.0f, 0.0f), WorldViewMatrix);
gTexFont.GetGlyphTriangles(PosY.x, PosY.y, PosY.z, 'Y', TextBuffer + 5 * 6);
lcVector3 PosZ = lcMul30(lcVector3(0.0f, 0.0f, 25.0f), WorldViewMatrix);
gTexFont.GetGlyphTriangles(PosZ.x, PosZ.y, PosZ.z, 'Z', TextBuffer + 5 * 6 * 2);
mContext->SetVertexBufferPointer(TextBuffer);
mContext->SetVertexFormat(0, 3, 0, 2, 0, false);
mContext->SetColor(lcVector4FromColor(lcGetPreferences().mAxesColor));
mContext->DrawPrimitives(GL_TRIANGLES, 0, 6 * 3);
glDisable(GL_BLEND);
}
void View::DrawSelectMoveOverlay()
{
mContext->SetMaterial(lcMaterialType::UnlitColor);
@ -1654,6 +1949,135 @@ void View::EndDrag(bool Accept)
ActiveModel->UpdateAllViews();
}
void View::SetViewpoint(lcViewpoint Viewpoint)
{
if (!mCamera || !mCamera->IsSimple())
{
lcCamera* OldCamera = mCamera;
mCamera = new lcCamera(true);
if (OldCamera)
mCamera->CopySettings(OldCamera);
}
mCamera->SetViewpoint(Viewpoint);
ZoomExtents();
Redraw();
emit CameraChanged();
}
void View::SetViewpoint(const lcVector3& Position)
{
if (!mCamera || !mCamera->IsSimple())
{
lcCamera* OldCamera = mCamera;
mCamera = new lcCamera(true);
if (OldCamera)
mCamera->CopySettings(OldCamera);
}
mCamera->SetViewpoint(Position);
ZoomExtents();
Redraw();
emit CameraChanged();
}
void View::SetViewpoint(const lcVector3& Position, const lcVector3& Target, const lcVector3& Up)
{
if (!mCamera || !mCamera->IsSimple())
{
lcCamera* OldCamera = mCamera;
mCamera = new lcCamera(true);
if (OldCamera)
mCamera->CopySettings(OldCamera);
}
mCamera->SetViewpoint(Position, Target, Up);
Redraw();
emit CameraChanged();
}
void View::SetCameraAngles(float Latitude, float Longitude)
{
if (!mCamera || !mCamera->IsSimple())
{
lcCamera* OldCamera = mCamera;
mCamera = new lcCamera(true);
if (OldCamera)
mCamera->CopySettings(OldCamera);
}
mCamera->SetAngles(Latitude, Longitude, 1.0f);
ZoomExtents();
Redraw();
}
void View::SetDefaultCamera()
{
if (!mCamera || !mCamera->IsSimple())
mCamera = new lcCamera(true);
mCamera->SetViewpoint(lcViewpoint::Home);
emit CameraChanged();
}
void View::SetCamera(lcCamera* Camera, bool ForceCopy)
{
if (Camera->IsSimple() || ForceCopy)
{
if (!mCamera || !mCamera->IsSimple())
mCamera = new lcCamera(true);
mCamera->CopyPosition(Camera);
}
else
{
if (mCamera && mCamera->IsSimple())
delete mCamera;
mCamera = Camera;
}
}
void View::SetCamera(const QString& CameraName)
{
const lcArray<lcCamera*>& Cameras = mModel->GetCameras();
for (int CameraIdx = 0; CameraIdx < Cameras.GetSize(); CameraIdx++)
{
if (CameraName.compare(Cameras[CameraIdx]->GetName(), Qt::CaseInsensitive) == 0)
{
SetCameraIndex(CameraIdx);
return;
}
}
}
void View::SetCameraIndex(int Index)
{
const lcArray<lcCamera*>& Cameras = mModel->GetCameras();
if (Index >= Cameras.GetSize())
return;
lcCamera* Camera = Cameras[Index];
SetCamera(Camera, false);
emit CameraChanged();
Redraw();
}
void View::SetProjection(bool Ortho)
{
if (mCamera->IsSimple())
@ -1692,6 +2116,174 @@ void View::Zoom(float Amount)
ActiveModel->Zoom(mCamera, Amount);
}
void View::ZoomExtents()
{
lcModel* ActiveModel = GetActiveModel();
if (ActiveModel)
ActiveModel->ZoomExtents(mCamera, (float)mWidth / (float)mHeight);
}
lcCursor View::GetCursor() const
{
if (mTrackButton != lcTrackButton::None)
return lcCursor::Hidden;
if (mTrackTool == lcTrackTool::Select)
{
if (mMouseModifiers & Qt::ControlModifier)
return lcCursor::SelectAdd;
if (mMouseModifiers & Qt::ShiftModifier)
return lcCursor::SelectRemove;
}
constexpr lcCursor CursorFromTrackTool[] =
{
lcCursor::Select, // lcTrackTool::None
lcCursor::Brick, // lcTrackTool::Insert
lcCursor::Light, // lcTrackTool::PointLight
lcCursor::Spotlight, // lcTrackTool::SpotLight
lcCursor::Camera, // lcTrackTool::Camera
lcCursor::Select, // lcTrackTool::Select
lcCursor::Move, // lcTrackTool::MoveX
lcCursor::Move, // lcTrackTool::MoveY
lcCursor::Move, // lcTrackTool::MoveZ
lcCursor::Move, // lcTrackTool::MoveXY
lcCursor::Move, // lcTrackTool::MoveXZ
lcCursor::Move, // lcTrackTool::MoveYZ
lcCursor::Move, // lcTrackTool::MoveXYZ
lcCursor::Rotate, // lcTrackTool::RotateX
lcCursor::Rotate, // lcTrackTool::RotateY
lcCursor::Rotate, // lcTrackTool::RotateZ
lcCursor::Rotate, // lcTrackTool::RotateXY
lcCursor::Rotate, // lcTrackTool::RotateXYZ
lcCursor::Move, // lcTrackTool::ScalePlus
lcCursor::Move, // lcTrackTool::ScaleMinus
lcCursor::Delete, // lcTrackTool::Eraser
lcCursor::Paint, // lcTrackTool::Paint
lcCursor::ColorPicker, // lcTrackTool::ColorPicker
lcCursor::Zoom, // lcTrackTool::Zoom
lcCursor::Pan, // lcTrackTool::Pan
lcCursor::RotateX, // lcTrackTool::OrbitX
lcCursor::RotateY, // lcTrackTool::OrbitY
lcCursor::RotateView, // lcTrackTool::OrbitXY
lcCursor::Roll, // lcTrackTool::Roll
lcCursor::ZoomRegion // lcTrackTool::ZoomRegion
};
LC_ARRAY_SIZE_CHECK(CursorFromTrackTool, lcTrackTool::Count);
if (mTrackTool >= lcTrackTool::None && mTrackTool < lcTrackTool::Count)
return CursorFromTrackTool[static_cast<int>(mTrackTool)];
return lcCursor::Select;
}
void View::SetCursor(lcCursor CursorType)
{
if (mCursor == CursorType)
return;
struct lcCursorInfo
{
int x, y;
const char* Name;
};
constexpr lcCursorInfo Cursors[] =
{
{ 0, 0, "" }, // lcCursor::Hidden
{ 0, 0, "" }, // lcCursor::Default
{ 8, 3, ":/resources/cursor_insert" }, // lcCursor::Brick
{ 15, 15, ":/resources/cursor_light" }, // lcCursor::Light
{ 7, 10, ":/resources/cursor_spotlight" }, // lcCursor::Spotlight
{ 15, 9, ":/resources/cursor_camera" }, // lcCursor::Camera
{ 0, 2, ":/resources/cursor_select" }, // lcCursor::Select
{ 0, 2, ":/resources/cursor_select_add" }, // lcCursor::SelectAdd
{ 0, 2, ":/resources/cursor_select_remove" }, // lcCursor::SelectRemove
{ 15, 15, ":/resources/cursor_move" }, // lcCursor::Move
{ 15, 15, ":/resources/cursor_rotate" }, // lcCursor::Rotate
{ 15, 15, ":/resources/cursor_rotatex" }, // lcCursor::RotateX
{ 15, 15, ":/resources/cursor_rotatey" }, // lcCursor::RotateY
{ 0, 10, ":/resources/cursor_delete" }, // lcCursor::Delete
{ 14, 14, ":/resources/cursor_paint" }, // lcCursor::Paint
{ 1, 13, ":/resources/cursor_color_picker" }, // lcCursor::ColorPicker
{ 15, 15, ":/resources/cursor_zoom" }, // lcCursor::Zoom
{ 9, 9, ":/resources/cursor_zoom_region" }, // lcCursor::ZoomRegion
{ 15, 15, ":/resources/cursor_pan" }, // lcCursor::Pan
{ 15, 15, ":/resources/cursor_roll" }, // lcCursor::Roll
{ 15, 15, ":/resources/cursor_rotate_view" }, // lcCursor::RotateView
};
LC_ARRAY_SIZE_CHECK(Cursors, lcCursor::Count);
if (CursorType == lcCursor::Hidden)
{
mWidget->setCursor(Qt::BlankCursor);
mCursor = CursorType;
}
else if (CursorType >= lcCursor::First && CursorType < lcCursor::Count)
{
const lcCursorInfo& Cursor = Cursors[static_cast<int>(CursorType)];
mWidget->setCursor(QCursor(QPixmap(Cursor.Name), Cursor.x, Cursor.y));
mCursor = CursorType;
}
else
{
mWidget->unsetCursor();
mCursor = lcCursor::Default;
}
}
void View::UpdateCursor()
{
SetCursor(GetCursor());
}
lcTool View::GetCurrentTool() const
{
constexpr lcTool ToolFromTrackTool[] =
{
lcTool::Select, // lcTrackTool::None
lcTool::Insert, // lcTrackTool::Insert
lcTool::Light, // lcTrackTool::PointLight
lcTool::SpotLight, // lcTrackTool::SpotLight
lcTool::Camera, // lcTrackTool::Camera
lcTool::Select, // lcTrackTool::Select
lcTool::Move, // lcTrackTool::MoveX
lcTool::Move, // lcTrackTool::MoveY
lcTool::Move, // lcTrackTool::MoveZ
lcTool::Move, // lcTrackTool::MoveXY
lcTool::Move, // lcTrackTool::MoveXZ
lcTool::Move, // lcTrackTool::MoveYZ
lcTool::Move, // lcTrackTool::MoveXYZ
lcTool::Rotate, // lcTrackTool::RotateX
lcTool::Rotate, // lcTrackTool::RotateY
lcTool::Rotate, // lcTrackTool::RotateZ
lcTool::Rotate, // lcTrackTool::RotateXY
lcTool::Rotate, // lcTrackTool::RotateXYZ
lcTool::Move, // lcTrackTool::ScalePlus
lcTool::Move, // lcTrackTool::ScaleMinus
lcTool::Eraser, // lcTrackTool::Eraser
lcTool::Paint, // lcTrackTool::Paint
lcTool::ColorPicker, // lcTrackTool::ColorPicker
lcTool::Zoom, // lcTrackTool::Zoom
lcTool::Pan, // lcTrackTool::Pan
lcTool::RotateView, // lcTrackTool::OrbitX
lcTool::RotateView, // lcTrackTool::OrbitY
lcTool::RotateView, // lcTrackTool::OrbitXY
lcTool::Roll, // lcTrackTool::Roll
lcTool::ZoomRegion // lcTrackTool::ZoomRegion
};
LC_ARRAY_SIZE_CHECK(ToolFromTrackTool, lcTrackTool::Count);
if (mTrackTool >= lcTrackTool::None && mTrackTool < lcTrackTool::Count)
return ToolFromTrackTool[static_cast<int>(mTrackTool)];
return lcTool::Select;
}
void View::UpdateTrackTool()
{
if (mViewType != lcViewType::View)
@ -2230,6 +2822,68 @@ void View::StartOrbitTracking()
OnButtonDown(lcTrackButton::Left);
}
void View::StartTracking(lcTrackButton TrackButton)
{
mTrackButton = TrackButton;
mTrackUpdated = false;
mMouseDownX = mMouseX;
mMouseDownY = mMouseY;
lcTool Tool = GetCurrentTool();
lcModel* ActiveModel = GetActiveModel();
switch (Tool)
{
case lcTool::Insert:
case lcTool::Light:
break;
case lcTool::SpotLight:
{
lcVector3 Position = GetCameraLightInsertPosition();
lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f);
ActiveModel->BeginSpotLightTool(Position, Target);
}
break;
case lcTool::Camera:
{
lcVector3 Position = GetCameraLightInsertPosition();
lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f);
ActiveModel->BeginCameraTool(Position, Target);
}
break;
case lcTool::Select:
break;
case lcTool::Move:
case lcTool::Rotate:
ActiveModel->BeginMouseTool();
break;
case lcTool::Eraser:
case lcTool::Paint:
case lcTool::ColorPicker:
break;
case lcTool::Zoom:
case lcTool::Pan:
case lcTool::RotateView:
case lcTool::Roll:
ActiveModel->BeginMouseTool();
break;
case lcTool::ZoomRegion:
break;
case lcTool::Count:
break;
}
UpdateCursor();
}
void View::StopTracking(bool Accept)
{
if (mTrackButton == lcTrackButton::None)
@ -2539,11 +3193,19 @@ void View::OnRightButtonUp()
ShowContextMenu();
}
void View::OnBackButtonDown()
{
}
void View::OnBackButtonUp()
{
gMainWindow->HandleCommand(LC_VIEW_TIME_PREVIOUS);
}
void View::OnForwardButtonDown()
{
}
void View::OnForwardButtonUp()
{
gMainWindow->HandleCommand(LC_VIEW_TIME_NEXT);
@ -2886,3 +3548,8 @@ void View::OnMouseMove()
break;
}
}
void View::OnMouseWheel(float Direction)
{
mModel->Zoom(mCamera, (int)(((mMouseModifiers & Qt::ControlModifier) ? 100 : 10) * Direction));
}

View file

@ -1,9 +1,95 @@
#pragma once
#include "lc_glwidget.h"
#include "lc_context.h"
#include "lc_math.h"
#include "lc_commands.h"
class View : public lcGLWidget
enum class lcDragState
{
None,
Piece,
Color
};
enum class lcCursor
{
First,
Hidden = First,
Default,
Brick,
Light,
Spotlight,
Camera,
Select,
SelectAdd,
SelectRemove,
Move,
Rotate,
RotateX,
RotateY,
Delete,
Paint,
ColorPicker,
Zoom,
ZoomRegion,
Pan,
Roll,
RotateView,
Count
};
enum class lcTrackButton
{
None,
Left,
Middle,
Right
};
enum class lcTrackTool
{
None,
Insert,
PointLight,
SpotLight,
Camera,
Select,
MoveX,
MoveY,
MoveZ,
MoveXY,
MoveXZ,
MoveYZ,
MoveXYZ,
RotateX,
RotateY,
RotateZ,
RotateXY,
RotateXYZ,
ScalePlus,
ScaleMinus,
Eraser,
Paint,
ColorPicker,
Zoom,
Pan,
OrbitX,
OrbitY,
OrbitXY,
Roll,
ZoomRegion,
Count
};
enum class lcViewType
{
View,
Preview,
Minifig,
Count
};
class View : public QObject
{
Q_OBJECT
@ -25,39 +111,122 @@ public:
return mModel;
}
void SetTopSubmodelActive();
void SetSelectedSubmodelActive();
lcViewType GetViewType() const
{
return mViewType;
}
lcCamera* GetCamera() const
{
return mCamera;
}
bool IsLastFocused() const
{
return mLastFocusedView == this;
}
bool IsTracking() const
{
return mTrackButton != lcTrackButton::None;
}
int GetWidth() const
{
return mWidth;
}
int GetHeight() const
{
return mHeight;
}
void SetSize(int Width, int Height)
{
mWidth = Width;
mHeight = Height;
}
QGLWidget* GetWidget() const
{
return mWidget;
}
void SetWidget(QGLWidget* Widget)
{
mWidget = Widget;
}
int GetMouseX() const
{
return mMouseX;
}
int GetMouseY() const
{
return mMouseY;
}
static void UpdateProjectViews(const Project* Project);
static void UpdateAllViews();
static void CreateResources(lcContext* Context);
static void DestroyResources(lcContext* Context);
void OnDraw() override;
void OnLeftButtonDown() override;
void OnLeftButtonUp() override;
void OnLeftButtonDoubleClick() override;
void OnMiddleButtonDown() override;
void OnMiddleButtonUp() override;
void OnRightButtonDown() override;
void OnRightButtonUp() override;
void OnBackButtonUp() override;
void OnForwardButtonUp() override;
void OnMouseMove() override;
void BeginDrag(lcDragState DragState) override;
void EndDrag(bool Accept) override;
void MakeCurrent();
void Redraw();
void SetContext(lcContext* Context);
void SetFocus(bool Focus);
void SetMousePosition(int MouseX, int MouseY);
void SetMouseModifiers(Qt::KeyboardModifiers MouseModifiers);
lcModel* GetActiveModel() const;
void SetTopSubmodelActive();
void SetSelectedSubmodelActive();
void OnDraw();
void OnLeftButtonDown();
void OnLeftButtonUp();
void OnLeftButtonDoubleClick();
void OnMiddleButtonDown();
void OnMiddleButtonUp();
void OnRightButtonDown();
void OnRightButtonUp();
void OnBackButtonDown();
void OnBackButtonUp();
void OnForwardButtonDown();
void OnForwardButtonUp();
void OnMouseMove();
void OnMouseWheel(float Direction);
void BeginDrag(lcDragState DragState);
void EndDrag(bool Accept);
void UpdateCursor();
void StartOrbitTracking();
void CancelTrackingOrClearSelection();
void SetViewpoint(lcViewpoint Viewpoint);
void SetViewpoint(const lcVector3& Position);
void SetViewpoint(const lcVector3& Position, const lcVector3& Target, const lcVector3& Up);
void SetCameraAngles(float Latitude, float Longitude);
void SetDefaultCamera();
void SetCamera(lcCamera* Camera, bool ForceCopy);
void SetCamera(const QString& CameraName);
void SetCameraIndex(int Index);
void SetProjection(bool Ortho);
void LookAt();
void MoveCamera(const lcVector3& Direction);
void Zoom(float Amount);
void ZoomExtents();
void RemoveCamera();
void ShowContextMenu() const;
lcVector3 GetMoveDirection(const lcVector3& Direction) const;
lcMatrix44 GetPieceInsertPosition(bool IgnoreSelected, PieceInfo* Info) const;
lcVector3 GetCameraLightInsertPosition() const;
void GetRayUnderPointer(lcVector3& Start, lcVector3& End) const;
lcObjectSection FindObjectUnderPointer(bool PiecesOnly, bool IgnoreSelected) const;
lcArray<lcObject*> FindObjectsInBox(float x1, float y1, float x2, float y2) const;
@ -70,22 +239,58 @@ public:
return mRenderImage;
}
lcContext* mContext = nullptr;
signals:
void FocusReceived();
void CameraChanged();
protected:
static void CreateSelectMoveOverlayMesh(lcContext* Context);
void DrawBackground() const;
void DrawViewport() const;
void DrawAxes() const;
void DrawSelectMoveOverlay();
void DrawRotateOverlay();
void DrawSelectZoomRegionOverlay();
void DrawRotateViewOverlay();
void DrawGrid();
lcVector3 ProjectPoint(const lcVector3& Point) const;
lcVector3 UnprojectPoint(const lcVector3& Point) const;
void UnprojectPoints(lcVector3* Points, int NumPoints) const;
lcMatrix44 GetProjectionMatrix() const;
lcMatrix44 GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, int CurrentTileWidth, int CurrentTileHeight) const;
lcCursor GetCursor() const;
void SetCursor(lcCursor Cursor);
lcTool GetCurrentTool() const;
void UpdateTrackTool();
bool IsTrackToolAllowed(lcTrackTool TrackTool, quint32 AllowedTransforms) const;
lcTrackTool GetOverrideTrackTool(Qt::MouseButton Button) const;
float GetOverlayScale() const;
void StartTracking(lcTrackButton TrackButton);
void StopTracking(bool Accept);
void OnButtonDown(lcTrackButton TrackButton);
lcMatrix44 GetTileProjectionMatrix(int CurrentRow, int CurrentColumn, int CurrentTileWidth, int CurrentTileHeight) const;
QGLWidget* mWidget = nullptr;
int mWidth = 1;
int mHeight = 1;
bool mDeleteContext = true;
lcViewType mViewType;
int mMouseX = 0;
int mMouseY = 0;
int mMouseDownX = 0;
int mMouseDownY = 0;
Qt::KeyboardModifiers mMouseModifiers = Qt::NoModifier;
bool mTrackUpdated = false;
lcTrackTool mTrackTool = lcTrackTool::None;
lcTrackButton mTrackButton = lcTrackButton::None;
lcCursor mCursor = lcCursor::Default;
lcDragState mDragState;
bool mTrackToolFromOverlay;
@ -94,9 +299,21 @@ protected:
QImage mRenderImage;
std::pair<lcFramebuffer, lcFramebuffer> mRenderFramebuffer;
std::unique_ptr<lcScene> mScene;
std::unique_ptr<lcViewSphere> mViewSphere;
lcModel* mModel = nullptr;
lcPiece* mActiveSubmodelInstance = nullptr;
lcMatrix44 mActiveSubmodelTransform;
lcCamera* mCamera = nullptr;
lcVertexBuffer mGridBuffer;
int mGridSettings[7];
static View* mLastFocusedView;
static std::vector<View*> mViews;
static lcVertexBuffer mRotateMoveVertexBuffer;
static lcIndexBuffer mRotateMoveIndexBuffer;
};

View file

@ -185,7 +185,6 @@ SOURCES += common/view.cpp \
common/lc_context.cpp \
common/lc_file.cpp \
common/lc_glextensions.cpp \
common/lc_glwidget.cpp \
common/lc_http.cpp \
common/lc_instructionsdialog.cpp \
common/lc_library.cpp \
@ -252,7 +251,6 @@ HEADERS += \
common/lc_glext.h \
common/lc_glextensions.h \
common/lc_global.h \
common/lc_glwidget.h \
common/lc_http.h \
common/lc_instructionsdialog.h \
common/lc_library.h \